bisu 1.10.2 → 2.1.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/CHANGELOG.md +16 -0
- data/Gemfile +2 -4
- data/Gemfile.lock +33 -28
- data/README.md +63 -31
- data/bisu.gemspec +5 -5
- data/lib/bisu/config.rb +9 -1
- data/lib/bisu/localizer.rb +8 -7
- data/lib/bisu/source/tolgee.rb +58 -0
- data/lib/bisu/version.rb +2 -2
- data/lib/bisu.rb +3 -0
- data/spec/fixtures/sample_tolgee_response.zip +0 -0
- data/spec/lib/bisu/localizer_spec.rb +14 -10
- data/spec/lib/bisu/source/tolgee_spec.rb +45 -0
- metadata +27 -11
- data/.ruby-version +0 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a53a95f2c8ca08de5f1b44a56f5648f3b3430d22f191a9a5637f9b6daa37bee9
|
|
4
|
+
data.tar.gz: b51d192672fdf321ba29f2ac1a4fdaf0728a615885f03fad317c566264531053
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 50543ddcc08ea0d0c09626e4d7cee4cc1dec6f575f81e229dce5d263c2b460237fafedc6a13256178cc4a87ccf4eedb290edd83cb5b8c7ca672d5ad6aea9f969
|
|
7
|
+
data.tar.gz: d7ecec10c7249f263566589dbb62af318ea9a59adb346265bc9500248c048d00507047ce55eab2e2f3527403910bbd67ed995eb16282fda2b6595ab1fbcbc848
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
All notable changes to this project will be documented in this file.
|
|
3
3
|
`Bisu` adheres to [Semantic Versioning](http://semver.org/).
|
|
4
4
|
|
|
5
|
+
## Unreleased
|
|
6
|
+
|
|
7
|
+
## [2.1.0](https://github.com/hole19/bisu/releases/tag/v2.1.0)
|
|
8
|
+
|
|
9
|
+
#### Fixed
|
|
10
|
+
- Fixes handling of % character on iOS localization
|
|
11
|
+
|
|
12
|
+
## [2.0.0](https://github.com/hole19/bisu/releases/tag/v2.0.0)
|
|
13
|
+
Released on 2023/12/07
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
- Add [Tolgee](https://tolgee.io/) as a source.
|
|
17
|
+
|
|
18
|
+
### Maintenance
|
|
19
|
+
- Upgrade to ruby 3.2
|
|
20
|
+
|
|
5
21
|
## [1.10.2](https://github.com/hole19/bisu/releases/tag/v1.10.2)
|
|
6
22
|
Released on 2021/08/30
|
|
7
23
|
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,51 +1,56 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
bisu (2.0.0)
|
|
5
|
+
colorize
|
|
6
|
+
rubyzip (>= 2.0.0)
|
|
7
|
+
safe_yaml (>= 1.0.0)
|
|
8
|
+
|
|
1
9
|
GEM
|
|
2
10
|
remote: https://rubygems.org/
|
|
3
11
|
specs:
|
|
4
|
-
addressable (2.8.
|
|
5
|
-
public_suffix (>= 2.0.2, <
|
|
6
|
-
colorize (
|
|
12
|
+
addressable (2.8.5)
|
|
13
|
+
public_suffix (>= 2.0.2, < 6.0)
|
|
14
|
+
colorize (1.1.0)
|
|
7
15
|
crack (0.4.5)
|
|
8
16
|
rexml
|
|
9
|
-
diff-lcs (1.
|
|
17
|
+
diff-lcs (1.5.0)
|
|
10
18
|
hashdiff (1.0.1)
|
|
11
|
-
public_suffix (
|
|
12
|
-
rake (13.0
|
|
13
|
-
rexml (3.2.
|
|
14
|
-
rspec (3.
|
|
15
|
-
rspec-core (~> 3.
|
|
16
|
-
rspec-expectations (~> 3.
|
|
17
|
-
rspec-mocks (~> 3.
|
|
18
|
-
rspec-core (3.
|
|
19
|
-
rspec-support (~> 3.
|
|
20
|
-
rspec-expectations (3.
|
|
19
|
+
public_suffix (5.0.3)
|
|
20
|
+
rake (13.1.0)
|
|
21
|
+
rexml (3.2.6)
|
|
22
|
+
rspec (3.12.0)
|
|
23
|
+
rspec-core (~> 3.12.0)
|
|
24
|
+
rspec-expectations (~> 3.12.0)
|
|
25
|
+
rspec-mocks (~> 3.12.0)
|
|
26
|
+
rspec-core (3.12.2)
|
|
27
|
+
rspec-support (~> 3.12.0)
|
|
28
|
+
rspec-expectations (3.12.3)
|
|
21
29
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
22
|
-
rspec-support (~> 3.
|
|
30
|
+
rspec-support (~> 3.12.0)
|
|
23
31
|
rspec-its (1.3.0)
|
|
24
32
|
rspec-core (>= 3.0.0)
|
|
25
33
|
rspec-expectations (>= 3.0.0)
|
|
26
|
-
rspec-mocks (3.
|
|
34
|
+
rspec-mocks (3.12.6)
|
|
27
35
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
28
|
-
rspec-support (~> 3.
|
|
29
|
-
rspec-support (3.
|
|
36
|
+
rspec-support (~> 3.12.0)
|
|
37
|
+
rspec-support (3.12.1)
|
|
38
|
+
rubyzip (2.3.2)
|
|
30
39
|
safe_yaml (1.0.5)
|
|
31
|
-
webmock (
|
|
32
|
-
addressable (>= 2.
|
|
40
|
+
webmock (3.19.1)
|
|
41
|
+
addressable (>= 2.8.0)
|
|
33
42
|
crack (>= 0.3.2)
|
|
34
|
-
hashdiff
|
|
43
|
+
hashdiff (>= 0.4.0, < 2.0.0)
|
|
35
44
|
|
|
36
45
|
PLATFORMS
|
|
37
46
|
ruby
|
|
38
47
|
|
|
39
48
|
DEPENDENCIES
|
|
40
|
-
|
|
49
|
+
bisu!
|
|
41
50
|
rake
|
|
42
51
|
rspec
|
|
43
52
|
rspec-its
|
|
44
|
-
|
|
45
|
-
webmock (~> 1.20)
|
|
46
|
-
|
|
47
|
-
RUBY VERSION
|
|
48
|
-
ruby 2.7.3p183
|
|
53
|
+
webmock (~> 3)
|
|
49
54
|
|
|
50
55
|
BUNDLED WITH
|
|
51
|
-
2.
|
|
56
|
+
2.4.22
|
data/README.md
CHANGED
|
@@ -4,13 +4,19 @@ Bisu 홀
|
|
|
4
4
|
[](https://travis-ci.org/hole19/bisu?branch=master)
|
|
5
5
|
[](http://rubygems.org/gems/bisu "View this project in Rubygems")
|
|
6
6
|
|
|
7
|
-
Bisu manages your app iOS, Android and RoR localization files for you. No more copy+paste induced errors!
|
|
7
|
+
Bisu manages your app [iOS](#ios), [Android](#android) and [RoR](#ruby-on-rails) localization files for you. No more copy+paste induced errors!
|
|
8
|
+
|
|
9
|
+
It works with the following sources out of the box:
|
|
10
|
+
- [URL](#url)
|
|
11
|
+
- [Tolgee](#tolgee)
|
|
12
|
+
- [Google Sheets](#google-sheets)
|
|
13
|
+
- [OneSky](#onesky)
|
|
8
14
|
|
|
9
15
|
<p align="center">
|
|
10
16
|
<img src="https://raw.githubusercontent.com/hole19/bisu/master/README_explanation.png" width="500">
|
|
11
17
|
</p>
|
|
12
18
|
|
|
13
|
-
|
|
19
|
+
Installation
|
|
14
20
|
-----
|
|
15
21
|
|
|
16
22
|
```
|
|
@@ -54,7 +60,9 @@ Setup your configuration file
|
|
|
54
60
|
language: pt
|
|
55
61
|
```
|
|
56
62
|
|
|
57
|
-
|
|
63
|
+
#### Sources
|
|
64
|
+
|
|
65
|
+
##### URL
|
|
58
66
|
|
|
59
67
|
```
|
|
60
68
|
dictionary:
|
|
@@ -62,7 +70,16 @@ Setup your configuration file
|
|
|
62
70
|
url: <A-GET-URL>
|
|
63
71
|
```
|
|
64
72
|
|
|
65
|
-
#####
|
|
73
|
+
##### Tolgee
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
dictionary:
|
|
77
|
+
type: tolgee
|
|
78
|
+
api_key: <TOLGEE-API-KEY>
|
|
79
|
+
host: <TOLGEE-CUSTOM-HOST> (default: app.tolgee.io)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
##### Google Sheets
|
|
66
83
|
|
|
67
84
|
1. First ["Publish to the web"](https://www.google.com/search?q=google+sheets+publish+to+web) your Google Sheet
|
|
68
85
|
1. Share only the sheet that contains the translations
|
|
@@ -77,7 +94,7 @@ Setup your configuration file
|
|
|
77
94
|
keys_column: <GOOGLE-DRIVE-KEY-COLUMN-TITLE>
|
|
78
95
|
```
|
|
79
96
|
|
|
80
|
-
##### OneSky
|
|
97
|
+
##### OneSky
|
|
81
98
|
|
|
82
99
|
```
|
|
83
100
|
dictionary:
|
|
@@ -88,7 +105,7 @@ Setup your configuration file
|
|
|
88
105
|
file_name: <ONE-SKY-FILE-NAME>
|
|
89
106
|
```
|
|
90
107
|
|
|
91
|
-
Create
|
|
108
|
+
Create translatable file templates
|
|
92
109
|
-----
|
|
93
110
|
|
|
94
111
|
Create a \*.translatable version for your platform specific localization files:
|
|
@@ -97,19 +114,10 @@ Create a \*.translatable version for your platform specific localization files:
|
|
|
97
114
|
*example: Localizable.strings.translatable*
|
|
98
115
|
|
|
99
116
|
```
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
/***********
|
|
106
|
-
* General
|
|
107
|
-
************/
|
|
108
|
-
|
|
109
|
-
"klGeneral_Delete" = "$kDelete$";
|
|
110
|
-
"klGeneral_Cancel" = "$kCancel$";
|
|
111
|
-
"klGeneral_Close" = "$kClose$";
|
|
112
|
-
"klRequestName" = "$kRequestName{user_name: %@}$";
|
|
117
|
+
"delete" = "$general.delete$";
|
|
118
|
+
"cancel" = "$general.cancel$";
|
|
119
|
+
"close" = "$general.close$";
|
|
120
|
+
"requestName" = "$request.name{user_name: %@}$";
|
|
113
121
|
```
|
|
114
122
|
|
|
115
123
|
##### Android
|
|
@@ -118,15 +126,11 @@ Create a \*.translatable version for your platform specific localization files:
|
|
|
118
126
|
```
|
|
119
127
|
<?xml version="1.0" encoding="utf-8"?>
|
|
120
128
|
|
|
121
|
-
<!-- $specialKComment1$ -->
|
|
122
|
-
<!-- $specialKComment2$ -->
|
|
123
|
-
<!-- Locale: $specialKLocale$; Language used: $specialKLanguage$ -->
|
|
124
|
-
|
|
125
129
|
<resources>
|
|
126
|
-
<string name="delete">$
|
|
127
|
-
<string name="cancel">$
|
|
128
|
-
<string name="close">$
|
|
129
|
-
<string name="request_name">$
|
|
130
|
+
<string name="delete">$general.delete$</string>
|
|
131
|
+
<string name="cancel">$general.cancel$</string>
|
|
132
|
+
<string name="close">$general.close$</string>
|
|
133
|
+
<string name="request_name">$request.name{user_name: %s}$</string>
|
|
130
134
|
</resources>
|
|
131
135
|
```
|
|
132
136
|
|
|
@@ -136,9 +140,37 @@ Create a \*.translatable version for your platform specific localization files:
|
|
|
136
140
|
```
|
|
137
141
|
$specialKLocale$:
|
|
138
142
|
resources:
|
|
139
|
-
delete: $
|
|
140
|
-
cancel: $
|
|
141
|
-
close: $
|
|
143
|
+
delete: $general.delete$
|
|
144
|
+
cancel: $general.cancel$
|
|
145
|
+
close: $general.close$
|
|
142
146
|
messages:
|
|
143
|
-
request_name: $
|
|
147
|
+
request_name: $request.name$
|
|
144
148
|
```
|
|
149
|
+
|
|
150
|
+
### Translatable options
|
|
151
|
+
|
|
152
|
+
#### Parameters
|
|
153
|
+
|
|
154
|
+
Given a key with params such as "Missing ${attribute} value"
|
|
155
|
+
- `$some-key-with-params{param: %s}$`: `Missing $s value`
|
|
156
|
+
- `$some-key-with-params//ignore-params$`: `Missing ${attribute} value`
|
|
157
|
+
|
|
158
|
+
#### Formated strings (special characters)
|
|
159
|
+
|
|
160
|
+
##### "%" character (iOS only)
|
|
161
|
+
|
|
162
|
+
When it should be localized as given such as "Perfect: 100 (%)"
|
|
163
|
+
- `$some-key-with-percentage$`: `Perfect: 100%`
|
|
164
|
+
|
|
165
|
+
When it should be localized as a formated string such as "Perfect: %{percentage} (%)"
|
|
166
|
+
- `$some-key-with-percentage{percentage: %d}//formatted-string$`: `Perfect: %d (%%)` (note the double `%`)
|
|
167
|
+
|
|
168
|
+
#### Locale (useful for Rails localization files)
|
|
169
|
+
|
|
170
|
+
- `$specialKLocale$`: the respective locale of this file
|
|
171
|
+
- `$specialKLanguage$`: the respective language on the translation platform
|
|
172
|
+
|
|
173
|
+
#### Special comments
|
|
174
|
+
|
|
175
|
+
- `$specialKComment1$`: `This file was automatically generated based on a translation template.`
|
|
176
|
+
- `$specialKComment2$`: `Remember to CHANGE THE TEMPLATE and not this file!`
|
data/bisu.gemspec
CHANGED
|
@@ -11,11 +11,11 @@ Gem::Specification.new do |s|
|
|
|
11
11
|
s.license = 'MIT'
|
|
12
12
|
s.homepage = 'https://github.com/hole19/bisu'
|
|
13
13
|
|
|
14
|
-
s.files
|
|
14
|
+
s.files = `git ls-files`.split("\n")
|
|
15
15
|
s.require_paths = ['lib']
|
|
16
|
+
s.executables = %w[ bisu ]
|
|
16
17
|
|
|
17
|
-
s.
|
|
18
|
-
|
|
19
|
-
s.add_runtime_dependency '
|
|
20
|
-
s.add_runtime_dependency 'colorize', '~> 0.7'
|
|
18
|
+
s.add_dependency 'safe_yaml', '>= 1.0.0'
|
|
19
|
+
s.add_dependency 'colorize'
|
|
20
|
+
s.add_runtime_dependency 'rubyzip', '>= 2.0.0' # For extracting the Tolgee zip file
|
|
21
21
|
end
|
data/lib/bisu/config.rb
CHANGED
|
@@ -83,10 +83,18 @@ module Bisu
|
|
|
83
83
|
},
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
+
TOLGEE_STRUCT = {
|
|
87
|
+
type: Hash,
|
|
88
|
+
elements: {
|
|
89
|
+
api_key: { type: String },
|
|
90
|
+
},
|
|
91
|
+
}
|
|
92
|
+
|
|
86
93
|
DICTIONARY_STRUCT = {
|
|
87
94
|
"google_sheet" => GOOGLE_SHEET_STRUCT,
|
|
88
95
|
"one_sky" => ONE_SKY_STRUCT,
|
|
89
|
-
"url" => URL_STRUCT
|
|
96
|
+
"url" => URL_STRUCT,
|
|
97
|
+
"tolgee" => TOLGEE_STRUCT,
|
|
90
98
|
}
|
|
91
99
|
end
|
|
92
100
|
end
|
data/lib/bisu/localizer.rb
CHANGED
|
@@ -19,7 +19,7 @@ module Bisu
|
|
|
19
19
|
|
|
20
20
|
to_localize(t).map do |l|
|
|
21
21
|
if localized = localize_key(l[:key], [language] + fallback_languages)
|
|
22
|
-
localized = process(localized)
|
|
22
|
+
localized = process(localized, l[:is_formatted_string])
|
|
23
23
|
|
|
24
24
|
l[:params].each do |param, value|
|
|
25
25
|
if localized.match("%{#{param}}")
|
|
@@ -33,8 +33,8 @@ module Bisu
|
|
|
33
33
|
Logger.warn("Could not find translation for #{l[:match]} in #{language}")
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
unless @type.eql?(:ror) || l[:
|
|
37
|
-
localized.scan(/%{[^}]+}/) { |match| Logger.error("Could not find translation param for #{match} in #{language}") }
|
|
36
|
+
unless @type.eql?(:ror) || l[:ignore_params] == true
|
|
37
|
+
localized.scan(/%{[^}]+}/) { |match| Logger.error("Could not find translation param for #{match} for #{l[:key]} in #{language}") }
|
|
38
38
|
end
|
|
39
39
|
else
|
|
40
40
|
Logger.warn("Could not find translation for #{l[:match]} in #{language}")
|
|
@@ -57,7 +57,7 @@ module Bisu
|
|
|
57
57
|
private
|
|
58
58
|
|
|
59
59
|
def to_localize(text)
|
|
60
|
-
all_matches = text.to_enum(:scan, /\$([^\$\{\/]+)(?:\{(.+)\})?(\/\/
|
|
60
|
+
all_matches = text.to_enum(:scan, /\$([^\$\{\/]+)(?:\{(.+)\})?(\/\/[A-Za-z-]+)*\$/).map { Regexp.last_match }
|
|
61
61
|
all_matches.map do |match|
|
|
62
62
|
params = if match[2]
|
|
63
63
|
params = match[2].split(",").map(&:strip).map do |param|
|
|
@@ -71,12 +71,13 @@ module Bisu
|
|
|
71
71
|
match: match[0],
|
|
72
72
|
key: match[1],
|
|
73
73
|
params: params || {},
|
|
74
|
-
|
|
74
|
+
ignore_params: text.include?("//ignore-params"),
|
|
75
|
+
is_formatted_string: text.include?("//formatted-string"),
|
|
75
76
|
}
|
|
76
77
|
end
|
|
77
78
|
end
|
|
78
79
|
|
|
79
|
-
def process(text)
|
|
80
|
+
def process(text, is_formatted_string)
|
|
80
81
|
text = text.gsub("\n", "\\n")
|
|
81
82
|
|
|
82
83
|
if @type.eql?(:android)
|
|
@@ -88,7 +89,7 @@ module Bisu
|
|
|
88
89
|
|
|
89
90
|
elsif @type.eql?(:ios)
|
|
90
91
|
text = text.gsub(/\"/, "\\\\\"")
|
|
91
|
-
text = text.gsub(/%(?!{)/, "%%")
|
|
92
|
+
text = text.gsub(/%(?!{)/, "%%") if is_formatted_string
|
|
92
93
|
end
|
|
93
94
|
|
|
94
95
|
text
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require 'net/https'
|
|
2
|
+
require 'json'
|
|
3
|
+
require 'zip'
|
|
4
|
+
|
|
5
|
+
module Bisu
|
|
6
|
+
module Source
|
|
7
|
+
class Tolgee
|
|
8
|
+
def initialize(api_key, custom_host = nil)
|
|
9
|
+
@api_key = api_key
|
|
10
|
+
@host = custom_host || "app.tolgee.io"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def to_i18
|
|
14
|
+
Logger.info("Downloading dictionary from Tolgee...")
|
|
15
|
+
|
|
16
|
+
hash = {}
|
|
17
|
+
export do |language, language_data|
|
|
18
|
+
hash[language] = language_data
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
Logger.info("Found #{hash.count} languages.")
|
|
22
|
+
|
|
23
|
+
hash
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
private
|
|
27
|
+
|
|
28
|
+
def export
|
|
29
|
+
uri = URI("https://#{@host}/v2/projects/export?format=JSON&structureDelimiter=")
|
|
30
|
+
|
|
31
|
+
request = Net::HTTP::Get.new(uri)
|
|
32
|
+
request['X-API-Key'] = @api_key
|
|
33
|
+
|
|
34
|
+
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
|
|
35
|
+
http.request(request)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
raise "Bisu::Source::Tolgee: Http Error #{response.body}" unless response.is_a?(Net::HTTPSuccess)
|
|
39
|
+
|
|
40
|
+
# Create a temporary directory to extract the zip file
|
|
41
|
+
temp_dir = Dir.mktmpdir
|
|
42
|
+
|
|
43
|
+
# Extract the zip archive
|
|
44
|
+
Zip::File.open_buffer(response.body) do |zip_file|
|
|
45
|
+
zip_file.each do |entry|
|
|
46
|
+
language = File.basename(entry.name, '.*') # Extract language from file name
|
|
47
|
+
language_data = JSON.parse(entry.get_input_stream.read)
|
|
48
|
+
|
|
49
|
+
yield language, language_data
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Clean up the temporary directory
|
|
54
|
+
FileUtils.remove_entry(temp_dir)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
data/lib/bisu/version.rb
CHANGED
data/lib/bisu.rb
CHANGED
|
@@ -8,6 +8,7 @@ require 'bisu/config'
|
|
|
8
8
|
require 'bisu/source/google_sheet'
|
|
9
9
|
require 'bisu/source/one_sky'
|
|
10
10
|
require 'bisu/source/url'
|
|
11
|
+
require 'bisu/source/tolgee'
|
|
11
12
|
require 'bisu/dictionary'
|
|
12
13
|
require 'bisu/localizer'
|
|
13
14
|
require 'bisu/version'
|
|
@@ -64,6 +65,8 @@ module Bisu
|
|
|
64
65
|
Bisu::Source::OneSky.new(config[:api_key], config[:api_secret], config[:project_id], config[:file_name])
|
|
65
66
|
when "url"
|
|
66
67
|
Bisu::Source::Url.new(config[:url])
|
|
68
|
+
when "tolgee"
|
|
69
|
+
Bisu::Source::Tolgee.new(config[:api_key], config[:host])
|
|
67
70
|
end
|
|
68
71
|
|
|
69
72
|
source = source.to_i18
|
|
Binary file
|
|
@@ -66,10 +66,11 @@ describe Bisu::Localizer do
|
|
|
66
66
|
|
|
67
67
|
it { translates("$kDoubleQuoted$", to: expected[:double_quoted]) }
|
|
68
68
|
it { translates("$kSingleQuoted$", to: expected[:single_quoted]) }
|
|
69
|
-
it { translates("$kEllipsis$",
|
|
70
|
-
it { translates("$kAmpersand$",
|
|
71
|
-
it { translates("$kAtSign$",
|
|
72
|
-
it { translates("$kPercentage$",
|
|
69
|
+
it { translates("$kEllipsis$", to: expected[:ellipsis]) }
|
|
70
|
+
it { translates("$kAmpersand$", to: expected[:ampersand]) }
|
|
71
|
+
it { translates("$kAtSign$", to: expected[:at_sign]) }
|
|
72
|
+
it { translates("$kPercentage$", to: expected[:percentage]) }
|
|
73
|
+
it { translates("$kPercentage//formatted-string$", to: expected[:percentage_formatted]) }
|
|
73
74
|
|
|
74
75
|
# error handling
|
|
75
76
|
|
|
@@ -130,10 +131,11 @@ describe Bisu::Localizer do
|
|
|
130
131
|
let(:type_dependent_defaults) { {
|
|
131
132
|
double_quoted: keys[language]["kDoubleQuoted"],
|
|
132
133
|
single_quoted: keys[language]["kSingleQuoted"],
|
|
133
|
-
ellipsis:
|
|
134
|
-
ampersand:
|
|
135
|
-
at_sign:
|
|
136
|
-
percentage:
|
|
134
|
+
ellipsis: keys[language]["kEllipsis"],
|
|
135
|
+
ampersand: keys[language]["kAmpersand"],
|
|
136
|
+
at_sign: keys[language]["kAtSign"],
|
|
137
|
+
percentage: keys[language]["kPercentage"],
|
|
138
|
+
percentage_formatted: keys[language]["kPercentage"],
|
|
137
139
|
} }
|
|
138
140
|
|
|
139
141
|
describe "of type iOS" do
|
|
@@ -141,7 +143,8 @@ describe Bisu::Localizer do
|
|
|
141
143
|
|
|
142
144
|
let(:expected) { type_dependent_defaults.merge(
|
|
143
145
|
double_quoted: "Não sabes nada \\\"João das Neves\\\"",
|
|
144
|
-
percentage: "Sabes 0
|
|
146
|
+
percentage: "Sabes 0% João das Neves.",
|
|
147
|
+
percentage_formatted: "Sabes 0%% João das Neves.",
|
|
145
148
|
) }
|
|
146
149
|
|
|
147
150
|
it_behaves_like "a localizer"
|
|
@@ -182,7 +185,8 @@ describe Bisu::Localizer do
|
|
|
182
185
|
ellipsis: "Não sabes nada João das Neves…",
|
|
183
186
|
ampersand: "Não sabes nada João das Neves & Pícaros",
|
|
184
187
|
at_sign: "\\@johnsnow sabes alguma coisa?",
|
|
185
|
-
percentage: "Sabes 0\\%% João das Neves."
|
|
188
|
+
percentage: "Sabes 0\\%% João das Neves.",
|
|
189
|
+
percentage_formatted: "Sabes 0\\%% João das Neves.",
|
|
186
190
|
) }
|
|
187
191
|
|
|
188
192
|
it_behaves_like "a localizer"
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
describe Bisu::Source::Tolgee do
|
|
2
|
+
subject(:to_i18) { Bisu::Source::Tolgee.new(api_key).to_i18 }
|
|
3
|
+
|
|
4
|
+
let(:api_key) { "a123" }
|
|
5
|
+
let(:os_response) { File.read("spec/fixtures/sample_tolgee_response.zip") }
|
|
6
|
+
|
|
7
|
+
def stub_url(status:, response:, host: "app.tolgee.io")
|
|
8
|
+
stub_request(:get, "https://#{host}/v2/projects/export?format=JSON&structureDelimiter=").
|
|
9
|
+
to_return(:status => status, :body => response, :headers => {})
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
before { stub_url(status: 200, response: os_response) }
|
|
13
|
+
|
|
14
|
+
it { expect { to_i18 }.not_to raise_error }
|
|
15
|
+
|
|
16
|
+
it "returns an hash in i18 format" do
|
|
17
|
+
expect(to_i18).to eq({
|
|
18
|
+
"en" => { "kConnectFacebook" => "Connect with Facebook", "kNoNoNoMr" => "No, no, no. Mr %{name} not here" },
|
|
19
|
+
"ja" => { "kConnectFacebook" => "フェイスブックへ接続" },
|
|
20
|
+
"fr" => { "kConnectFacebook" => "Connexion par Facebook" },
|
|
21
|
+
"de" => { "kConnectFacebook" => "Mit Facebook verbinden" },
|
|
22
|
+
"ko" => { "kConnectFacebook" => "페이스북으로 접속", "kTwitterServer" => "트위터 서버연결 실패. \\n잠시 후 재시도." }
|
|
23
|
+
})
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context "when get request to that URL raises an error" do
|
|
27
|
+
before { stub_url(status: 400, response: { error: "ups... not allowed!" }.to_json) }
|
|
28
|
+
|
|
29
|
+
it "raises that same error" do
|
|
30
|
+
expect { to_i18 }.to raise_error /not allowed/
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
context "with a custom host" do
|
|
35
|
+
let(:host) { "translations.example.com" }
|
|
36
|
+
subject(:to_i18) { Bisu::Source::Tolgee.new(api_key, host).to_i18 }
|
|
37
|
+
|
|
38
|
+
before { stub_url(status: 200, response: os_response, host: host) }
|
|
39
|
+
|
|
40
|
+
it "uses that host" do
|
|
41
|
+
to_i18
|
|
42
|
+
expect(WebMock).to have_requested(:get, "https://translations.example.com/v2/projects/export?format=JSON&structureDelimiter=")
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
metadata
CHANGED
|
@@ -1,43 +1,57 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bisu
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 2.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- joaoffcosta
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2023-12-18 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: safe_yaml
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- - "
|
|
17
|
+
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version:
|
|
19
|
+
version: 1.0.0
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
|
-
- - "
|
|
24
|
+
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
|
-
version:
|
|
26
|
+
version: 1.0.0
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: colorize
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
|
-
- - "
|
|
31
|
+
- - ">="
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '0
|
|
33
|
+
version: '0'
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
|
-
- - "
|
|
38
|
+
- - ">="
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '0
|
|
40
|
+
version: '0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rubyzip
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: 2.0.0
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: 2.0.0
|
|
41
55
|
description: Bisu manages your app iOS and Android localization files for you. No
|
|
42
56
|
more copy+paste induced errors!
|
|
43
57
|
email: joaostacosta@gmail.com
|
|
@@ -47,7 +61,6 @@ extensions: []
|
|
|
47
61
|
extra_rdoc_files: []
|
|
48
62
|
files:
|
|
49
63
|
- ".rspec"
|
|
50
|
-
- ".ruby-version"
|
|
51
64
|
- ".travis.yml"
|
|
52
65
|
- CHANGELOG.md
|
|
53
66
|
- Gemfile
|
|
@@ -66,6 +79,7 @@ files:
|
|
|
66
79
|
- lib/bisu/object_extension.rb
|
|
67
80
|
- lib/bisu/source/google_sheet.rb
|
|
68
81
|
- lib/bisu/source/one_sky.rb
|
|
82
|
+
- lib/bisu/source/tolgee.rb
|
|
69
83
|
- lib/bisu/source/url.rb
|
|
70
84
|
- lib/bisu/version.rb
|
|
71
85
|
- spec/fixtures/sample.translatable.yml
|
|
@@ -73,6 +87,7 @@ files:
|
|
|
73
87
|
- spec/fixtures/sample_json_response.json
|
|
74
88
|
- spec/fixtures/sample_one_sky_response.json
|
|
75
89
|
- spec/fixtures/sample_one_sky_response_with_bug.json
|
|
90
|
+
- spec/fixtures/sample_tolgee_response.zip
|
|
76
91
|
- spec/lib/bisu/config_spec.rb
|
|
77
92
|
- spec/lib/bisu/dictionary_spec.rb
|
|
78
93
|
- spec/lib/bisu/localizer_spec.rb
|
|
@@ -80,6 +95,7 @@ files:
|
|
|
80
95
|
- spec/lib/bisu/object_extension_spec.rb
|
|
81
96
|
- spec/lib/bisu/source/google_sheet_spec.rb
|
|
82
97
|
- spec/lib/bisu/source/one_sky_spec.rb
|
|
98
|
+
- spec/lib/bisu/source/tolgee_spec.rb
|
|
83
99
|
- spec/lib/bisu/source/url_spec.rb
|
|
84
100
|
- spec/lib/bisu_spec.rb
|
|
85
101
|
- spec/spec_helper.rb
|
data/.ruby-version
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2.7.3
|