poesie 1.4.0 → 1.5.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/README.md +2 -1
- data/bin/poesie +22 -19
- data/lib/android_formatter.rb +14 -4
- data/lib/apple_formatter.rb +22 -53
- data/lib/context_formatter.rb +55 -0
- data/lib/filters.rb +6 -0
- data/lib/poesie.rb +2 -0
- data/lib/version.rb +1 -1
- metadata +12 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 147a5398c7444cb641b250e3b38a8394bf335d02
|
4
|
+
data.tar.gz: 944bde3b16366fa7ebf8cf1fba0721fc14bb5561
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 759e06722d8d15a7a73b728abe2cff5e07acbcecd0c00a9a2ffdd3cbdda6f8695ec1245e3b2fef37f6afd0b52821d76a8edbe576184c7aa62269852dcee99fc7
|
7
|
+
data.tar.gz: 5644643aaca8bcf56e24ea9989b2959c426b2eccaabd21dd935e90afd570da48db547595dd8e35d03a8ac38004ec9bb735d855a4135fbdb8392774c894ed73cc
|
data/README.md
CHANGED
@@ -77,7 +77,8 @@ Of course, only list in POEditor the strings that needs a translation (user-faci
|
|
77
77
|
### Naming your terms
|
78
78
|
|
79
79
|
* Find a name for your term that is consistent with existing keys
|
80
|
-
* As a convention, for Niji projects, we structure the name of terms in a reverse-dns hierarchical text, using `_` as a separator. For example `home_banner_text` and `home_weather_temperature
|
80
|
+
* As a convention, for Niji projects, we structure the name of terms in a reverse-dns hierarchical text, using `_` as a separator. For example `home_banner_text` and `home_weather_temperature`.
|
81
|
+
* For Android, if you have `.` in term names, they will be replaced with `_` (as `R.string.foo.bar` won't work in Android but `R.string.foo_bar` will)
|
81
82
|
* If a key should only be exported for Android, use the `_android` suffix. If a key should only be exported for iOS, use the `_ios` suffix.
|
82
83
|
|
83
84
|
### Using `%…` placeholders
|
data/bin/poesie
CHANGED
@@ -52,11 +52,11 @@ opts = OptionParser.new do |opts|
|
|
52
52
|
options[:print_date] = true
|
53
53
|
end
|
54
54
|
opts.on('-s FILE', '--subst FILE', %q(Path to a YAML file listing all substitutions)) do |path|
|
55
|
-
Poesie.exit_with_error("The substitutions file #{path} was not found") unless File.exists?(path)
|
55
|
+
Poesie.exit_with_error("The substitutions file #{path} was not found") unless File.exists?(path)
|
56
56
|
begin
|
57
57
|
subst = YAML.load_file(path)
|
58
58
|
rescue Psych::SyntaxError => e
|
59
|
-
Poesie.exit_with_error("Invalid YAML file #{e.message}")
|
59
|
+
Poesie.exit_with_error("Invalid YAML file #{e.message}")
|
60
60
|
end
|
61
61
|
subst = [subst] if subst.is_a?(Hash)
|
62
62
|
valid = subst.all? { |hash| hash.keys.all? { |k| k.is_a?(String) } && hash.values.all? { |k| k.is_a?(String) } }
|
@@ -81,12 +81,14 @@ Poesie.exit_with_error('You need to specify your POEditor project identifier usi
|
|
81
81
|
exporter = Poesie::Exporter.new(options[:api_token], options[:project_id])
|
82
82
|
Poesie.exit_with_error('You need to specify your POEditor project language using --lang option (see --help for more info)') if options[:lang].nil?
|
83
83
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
84
|
+
exporter.run(options[:lang]) do |terms|
|
85
|
+
Poesie::Log::title("== Language #{options[:lang]} ==")
|
86
|
+
|
87
|
+
# iOS
|
88
|
+
unless options[:localizable_strings].nil?
|
89
|
+
Poesie::Log::subtitle('== iOS ==')
|
90
|
+
|
88
91
|
# Localizable.strings
|
89
|
-
Poesie::Log::subtitle("== Language #{options[:lang]} ==")
|
90
92
|
Poesie::AppleFormatter::write_strings_file(
|
91
93
|
terms,
|
92
94
|
options[:localizable_strings],
|
@@ -102,21 +104,13 @@ unless options[:localizable_strings].nil?
|
|
102
104
|
substitutions: options[:substitutions],
|
103
105
|
print_date: options[:print_date]
|
104
106
|
)
|
105
|
-
|
106
|
-
# Context.json (if specified)
|
107
|
-
if options[:context_file]
|
108
|
-
Poesie::Log::subtitle("== Context #{options[:context_file]} ==")
|
109
|
-
Poesie::AppleFormatter::write_context_json(terms, options[:context_file])
|
110
|
-
end
|
111
107
|
end
|
112
|
-
end
|
113
108
|
|
114
|
-
# Android
|
115
|
-
unless options[:strings_xml].nil?
|
116
|
-
|
117
|
-
|
109
|
+
# Android
|
110
|
+
unless options[:strings_xml].nil?
|
111
|
+
Poesie::Log::subtitle('== Android ==')
|
112
|
+
|
118
113
|
# Strings.xml
|
119
|
-
Poesie::Log::subtitle("== Language #{options[:lang]} ==")
|
120
114
|
Poesie::AndroidFormatter::write_strings_xml(
|
121
115
|
terms,
|
122
116
|
options[:strings_xml],
|
@@ -124,4 +118,13 @@ unless options[:strings_xml].nil?
|
|
124
118
|
print_date: options[:print_date]
|
125
119
|
)
|
126
120
|
end
|
121
|
+
|
122
|
+
# Context.json (if specified)
|
123
|
+
if options[:context_file]
|
124
|
+
filters = nil
|
125
|
+
filters = Poesie::Filters::EXCLUDE_IOS if options[:localizable_strings].nil?
|
126
|
+
filters = Poesie::Filters::EXCLUDE_ANDROID if options[:strings_xml].nil?
|
127
|
+
Poesie::Log::subtitle("== Context ==")
|
128
|
+
Poesie::ContextFormatter::write_context_json(terms, options[:context_file], exclude: filters)
|
129
|
+
end
|
127
130
|
end
|
data/lib/android_formatter.rb
CHANGED
@@ -13,9 +13,12 @@ module Poesie
|
|
13
13
|
# The list of substitutions to apply to the translations
|
14
14
|
# @param [Bool] print_date
|
15
15
|
# Should we print the date in the header of the generated file
|
16
|
+
# @param [Regexp] exclude
|
17
|
+
# A regular expression to filter out terms.
|
18
|
+
# Terms matching this Regexp will be ignored and won't be part of the generated file
|
16
19
|
#
|
17
|
-
def self.write_strings_xml(terms, file, substitutions: nil, print_date: false)
|
18
|
-
stats = { :
|
20
|
+
def self.write_strings_xml(terms, file, substitutions: nil, print_date: false, exclude: Poesie::Filters::EXCLUDE_IOS)
|
21
|
+
stats = { :excluded => 0, :nil => [], :count => 0 }
|
19
22
|
|
20
23
|
Log::info(" - Save to file: #{file}")
|
21
24
|
File.open(file, "w") do |fh|
|
@@ -30,9 +33,13 @@ module Poesie
|
|
30
33
|
|
31
34
|
# Filter terms and update stats
|
32
35
|
next if (term.nil? || term.empty? || definition.nil?) && stats[:nil] << term
|
33
|
-
next if (term =~
|
36
|
+
next if (term =~ exclude) && stats[:excluded] += 1
|
34
37
|
stats[:count] += 1
|
35
38
|
|
39
|
+
# Terms with dots are invalid in Android ("R.string.foo.bar" won't work), so replace dots with underscores
|
40
|
+
term.gsub!('.', '_')
|
41
|
+
plurals.gsub!('.', '_')
|
42
|
+
|
36
43
|
xml_builder.comment!(context) unless context.empty?
|
37
44
|
if plurals.empty?
|
38
45
|
definition = Poesie::process(definition, substitutions).gsub('"', '\\"')
|
@@ -49,7 +56,10 @@ module Poesie
|
|
49
56
|
end
|
50
57
|
end
|
51
58
|
|
52
|
-
Log::info(" [Stats] #{stats[:count]} strings processed
|
59
|
+
Log::info(" [Stats] #{stats[:count]} strings processed")
|
60
|
+
unless exclude.nil?
|
61
|
+
Log::info(" Filtered out #{stats[:excluded]} strings matching #{exclude.inspect})")
|
62
|
+
end
|
53
63
|
unless stats[:nil].empty?
|
54
64
|
Log::error(" Found #{stats[:nil].count} empty value(s) for the following term(s):")
|
55
65
|
stats[:nil].each { |key| Log::error(" - #{key.inspect}") }
|
data/lib/apple_formatter.rb
CHANGED
@@ -13,20 +13,23 @@ module Poesie
|
|
13
13
|
# The list of substitutions to apply to the translations
|
14
14
|
# @param [Bool] print_date
|
15
15
|
# Should we print the date in the header of the generated file
|
16
|
+
# @param [Regexp] exclude
|
17
|
+
# A regular expression to filter out terms.
|
18
|
+
# Terms matching this Regexp will be ignored and won't be part of the generated file
|
16
19
|
#
|
17
|
-
def self.write_strings_file(terms, file, substitutions: nil, print_date: false)
|
20
|
+
def self.write_strings_file(terms, file, substitutions: nil, print_date: false, exclude: Poesie::Filters::EXCLUDE_ANDROID)
|
18
21
|
out_lines = ['/'+'*'*79, ' * Exported from POEditor - https://poeditor.com']
|
19
22
|
out_lines << " * #{Time.now}" if print_date
|
20
23
|
out_lines += [' '+'*'*79+'/', '']
|
21
24
|
last_prefix = ''
|
22
|
-
stats = { :
|
25
|
+
stats = { :excluded => 0, :nil => [], :count => 0 }
|
23
26
|
|
24
27
|
terms.each do |term|
|
25
28
|
(term, definition, comment, context) = ['term', 'definition', 'comment', 'context'].map { |k| term[k] }
|
26
29
|
|
27
30
|
# Filter terms and update stats
|
28
31
|
next if (term.nil? || term.empty? || definition.nil? || definition.empty?) && stats[:nil] << term
|
29
|
-
next if (term =~
|
32
|
+
next if (term =~ exclude) && stats[:excluded] += 1
|
30
33
|
stats[:count] += 1
|
31
34
|
|
32
35
|
# Generate MARK from prefixes
|
@@ -57,7 +60,10 @@ module Poesie
|
|
57
60
|
File.open(file, "w") do |fh|
|
58
61
|
fh.write(content)
|
59
62
|
end
|
60
|
-
Log::info(" [Stats] #{stats[:count]} strings processed
|
63
|
+
Log::info(" [Stats] #{stats[:count]} strings processed")
|
64
|
+
unless exclude.nil?
|
65
|
+
Log::info(" Filtered out #{stats[:excluded]} strings matching #{exclude.inspect})")
|
66
|
+
end
|
61
67
|
unless stats[:nil].empty?
|
62
68
|
Log::error(" Found #{stats[:nil].count} empty value(s) for the following term(s):")
|
63
69
|
stats[:nil].each { |key| Log::error(" - #{key.inspect}") }
|
@@ -74,9 +80,12 @@ module Poesie
|
|
74
80
|
# The list of substitutions to apply to the translations
|
75
81
|
# @param [Bool] print_date
|
76
82
|
# Should we print the date in the header of the generated file
|
83
|
+
# @param [Regexp] exclude
|
84
|
+
# A regular expression to filter out terms.
|
85
|
+
# Terms matching this Regexp will be ignored and won't be part of the generated file
|
77
86
|
#
|
78
|
-
def self.write_stringsdict_file(terms, file, substitutions: nil, print_date: false)
|
79
|
-
stats = { :
|
87
|
+
def self.write_stringsdict_file(terms, file, substitutions: nil, print_date: false, exclude: Poesie::Filters::EXCLUDE_ANDROID)
|
88
|
+
stats = { :excluded => 0, :nil => [], :count => 0 }
|
80
89
|
|
81
90
|
Log::info(" - Save to file: #{file}")
|
82
91
|
File.open(file, "w") do |fh|
|
@@ -92,10 +101,10 @@ module Poesie
|
|
92
101
|
|
93
102
|
# Filter terms and update stats
|
94
103
|
next if (term.nil? || term.empty? || definition.nil?) && stats[:nil] << term
|
95
|
-
next if (term =~
|
104
|
+
next if (term =~ exclude) && stats[:excluded] += 1
|
96
105
|
next unless definition.is_a? Hash
|
97
106
|
stats[:count] += 1
|
98
|
-
|
107
|
+
|
99
108
|
key = term_plural || term
|
100
109
|
|
101
110
|
root_node.key(key)
|
@@ -124,55 +133,15 @@ module Poesie
|
|
124
133
|
end
|
125
134
|
end
|
126
135
|
end
|
127
|
-
|
136
|
+
|
137
|
+
Log::info(" [Stats] #{stats[:count]} strings processed")
|
138
|
+
unless exclude.nil?
|
139
|
+
Log::info(" Filtered out #{stats[:excluded]} strings matching #{exclude.inspect})")
|
140
|
+
end
|
128
141
|
unless stats[:nil].empty?
|
129
142
|
Log::error(" Found #{stats[:nil].count} empty value(s) for the following term(s):")
|
130
143
|
stats[:nil].each { |key| Log::error(" - #{key.inspect}") }
|
131
144
|
end
|
132
145
|
end
|
133
|
-
|
134
|
-
# Write the JSON output file containing all context keys
|
135
|
-
#
|
136
|
-
# @param [Array<Hash<String, Any>>] terms
|
137
|
-
# JSON returned by the POEditor API
|
138
|
-
# @param [String] file
|
139
|
-
# The path of the file to write
|
140
|
-
#
|
141
|
-
def self.write_context_json(terms, file)
|
142
|
-
json_hash = { "date" => "#{Time.now}" }
|
143
|
-
|
144
|
-
stats = { :android => 0, :nil => 0, :count => 0 }
|
145
|
-
|
146
|
-
#switch on term / context
|
147
|
-
array_context = Array.new
|
148
|
-
terms.each do |term|
|
149
|
-
(term, definition, comment, context) = ['term', 'definition', 'comment', 'context'].map { |k| term[k] }
|
150
|
-
|
151
|
-
# Filter terms and update stats
|
152
|
-
next if (term.nil? || term.empty? || context.nil? || context.empty?) && stats[:nil] += 1
|
153
|
-
next if (term =~ /_android$/) && stats[:android] += 1 # Remove android-specific strings
|
154
|
-
stats[:count] += 1
|
155
|
-
|
156
|
-
# Escape some chars
|
157
|
-
context = context
|
158
|
-
.gsub("\u2028", '') # Sometimes inserted by the POEditor exporter
|
159
|
-
.gsub("\\", "\\\\\\") # Replace actual \ with \\
|
160
|
-
.gsub('\\\\"', '\\"') # Replace actual \\" with \"
|
161
|
-
.gsub(/%(\d+\$)?s/, '%\1@') # replace %s with %@ for iOS
|
162
|
-
|
163
|
-
array_context << { "term" => "#{term}", "context" => "#{context}" }
|
164
|
-
end
|
165
|
-
|
166
|
-
json_hash[:"contexts"] = array_context
|
167
|
-
|
168
|
-
context_json = JSON.pretty_generate(json_hash)
|
169
|
-
|
170
|
-
Log::info(" - Save to file: #{file}")
|
171
|
-
File.open(file, "w") do |fh|
|
172
|
-
fh.write(context_json)
|
173
|
-
end
|
174
|
-
Log::info(" [Stats] #{stats[:count]} contexts processed (Filtered out #{stats[:android]} android entries, #{stats[:nil]} nil contexts)")
|
175
|
-
end
|
176
|
-
|
177
146
|
end
|
178
147
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Poesie
|
2
|
+
module ContextFormatter
|
3
|
+
|
4
|
+
# Write the JSON output file containing all context keys
|
5
|
+
#
|
6
|
+
# @param [Array<Hash<String, Any>>] terms
|
7
|
+
# JSON returned by the POEditor API
|
8
|
+
# @param [String] file
|
9
|
+
# The path of the file to write
|
10
|
+
# @param [Regexp] exclude
|
11
|
+
# A regular expression to filter out terms.
|
12
|
+
# Terms matching this Regexp will be ignored and won't be part of the generated file
|
13
|
+
#
|
14
|
+
def self.write_context_json(terms, file, exclude: nil)
|
15
|
+
|
16
|
+
json_hash = { "date" => "#{Time.now}" }
|
17
|
+
|
18
|
+
stats = { :excluded => 0, :nil => 0, :count => 0 }
|
19
|
+
|
20
|
+
#switch on term / context
|
21
|
+
array_context = Array.new
|
22
|
+
terms.each do |term|
|
23
|
+
(term, definition, comment, context) = ['term', 'definition', 'comment', 'context'].map { |k| term[k] }
|
24
|
+
|
25
|
+
# Filter terms and update stats
|
26
|
+
next if (term.nil? || term.empty? || context.nil? || context.empty?) && stats[:nil] += 1
|
27
|
+
next if (term =~ exclude) && stats[:excluded] += 1 # Remove android-specific strings
|
28
|
+
|
29
|
+
stats[:count] += 1
|
30
|
+
|
31
|
+
# Escape some chars
|
32
|
+
context = context
|
33
|
+
.gsub("\u2028", '') # Sometimes inserted by the POEditor exporter
|
34
|
+
.gsub("\\", "\\\\\\") # Replace actual \ with \\
|
35
|
+
.gsub('\\\\"', '\\"') # Replace actual \\" with \"
|
36
|
+
.gsub(/%(\d+\$)?s/, '%\1@') # replace %s with %@ for iOS
|
37
|
+
|
38
|
+
array_context << { "term" => "#{term}", "context" => "#{context}" }
|
39
|
+
end
|
40
|
+
|
41
|
+
json_hash[:"contexts"] = array_context
|
42
|
+
|
43
|
+
context_json = JSON.pretty_generate(json_hash)
|
44
|
+
|
45
|
+
Log::info(" - Save to file: #{file}")
|
46
|
+
File.open(file, "w") do |fh|
|
47
|
+
fh.write(context_json)
|
48
|
+
end
|
49
|
+
Log::info(" [Stats] #{stats[:count]} strings processed")
|
50
|
+
unless exclude.nil?
|
51
|
+
Log::info(" Filtered out #{stats[:excluded]} strings matching #{exclude.inspect})")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/filters.rb
ADDED
data/lib/poesie.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
require File.expand_path('log', File.dirname(__FILE__))
|
2
2
|
require File.expand_path('exporter', File.dirname(__FILE__))
|
3
|
+
require File.expand_path('filters', File.dirname(__FILE__))
|
3
4
|
require File.expand_path('android_formatter', File.dirname(__FILE__))
|
4
5
|
require File.expand_path('apple_formatter', File.dirname(__FILE__))
|
6
|
+
require File.expand_path('context_formatter', File.dirname(__FILE__))
|
5
7
|
|
6
8
|
require 'json'
|
7
9
|
|
data/lib/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: poesie
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Olivier Halligon
|
@@ -9,48 +9,48 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2017-02-
|
12
|
+
date: 2017-02-10 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: net
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- - ~>
|
18
|
+
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
20
|
version: '0.3'
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
|
-
- - ~>
|
25
|
+
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '0.3'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: activesupport
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
|
-
- - ~>
|
32
|
+
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
34
|
version: '4.2'
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
|
-
- - ~>
|
39
|
+
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: '4.2'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: builder
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- - ~>
|
46
|
+
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
48
|
version: '3.0'
|
49
49
|
type: :runtime
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
|
-
- - ~>
|
53
|
+
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: '3.0'
|
56
56
|
description: This script automates the export of POEditor strings to iOS and Android
|
@@ -66,7 +66,9 @@ files:
|
|
66
66
|
- bin/poesie
|
67
67
|
- lib/android_formatter.rb
|
68
68
|
- lib/apple_formatter.rb
|
69
|
+
- lib/context_formatter.rb
|
69
70
|
- lib/exporter.rb
|
71
|
+
- lib/filters.rb
|
70
72
|
- lib/log.rb
|
71
73
|
- lib/poesie.rb
|
72
74
|
- lib/version.rb
|
@@ -80,12 +82,12 @@ require_paths:
|
|
80
82
|
- lib
|
81
83
|
required_ruby_version: !ruby/object:Gem::Requirement
|
82
84
|
requirements:
|
83
|
-
- -
|
85
|
+
- - ">="
|
84
86
|
- !ruby/object:Gem::Version
|
85
87
|
version: 2.0.0
|
86
88
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
89
|
requirements:
|
88
|
-
- -
|
90
|
+
- - ">="
|
89
91
|
- !ruby/object:Gem::Version
|
90
92
|
version: '0'
|
91
93
|
requirements: []
|