aigu 0.3.1 → 0.4
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/.rubocop.yml +52 -0
- data/README.md +89 -5
- data/Rakefile +1 -1
- data/aigu.gemspec +7 -4
- data/bin/aigu +1 -1
- data/bin/phare +16 -0
- data/lib/aigu.rb +11 -0
- data/lib/aigu/android_exporter.rb +165 -0
- data/lib/aigu/android_importer.rb +130 -0
- data/lib/aigu/cli.rb +14 -9
- data/lib/aigu/core_exporter.rb +82 -0
- data/lib/aigu/core_importer.rb +82 -0
- data/lib/aigu/exporter.rb +1 -5
- data/lib/aigu/extensions/hash.rb +6 -0
- data/lib/aigu/importer.rb +1 -3
- data/lib/aigu/ios_exporter.rb +165 -0
- data/lib/aigu/ios_importer.rb +181 -0
- data/lib/aigu/mergeer.rb +51 -0
- data/lib/aigu/puller.rb +44 -0
- data/lib/aigu/pusher.rb +44 -0
- data/lib/aigu/unmergeer.rb +55 -0
- data/lib/aigu/version.rb +1 -1
- data/spec/aigu/android_exporter_spec.rb +40 -0
- data/spec/aigu/android_importer_spec.rb +131 -0
- data/spec/aigu/core_exporter_spec.rb +53 -0
- data/spec/aigu/core_importer_spec.rb +102 -0
- data/spec/aigu/exporter_spec.rb +2 -2
- data/spec/aigu/importer_spec.rb +2 -2
- data/spec/aigu/ios_exporter_spec.rb +115 -0
- data/spec/aigu/ios_importer_spec.rb +175 -0
- data/spec/spec_helper.rb +7 -1
- metadata +72 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1891efbb20cc81f439f20f30fb4d74586e09c2c9
|
4
|
+
data.tar.gz: 2715fb01c3d8f203c791ffc55357469b077ad793
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 83421bf2129630b61d54543cfa484963415151301c345fd624febb67d65de937a45634173c54fb3017c5a3c3a3f95f3ab92ce1f814b147c99a560336f675f390
|
7
|
+
data.tar.gz: 3a60ed45b7ee4764a8b809cb297e8a9b9a7bfa395ae683cd335009308b189a8bb56039e39e099abee88c5a637a3e1f9ac635b10bf575b5c40bdfc32b33b562ab
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
AllCops:
|
2
|
+
Include:
|
3
|
+
- Rakefile
|
4
|
+
Exclude:
|
5
|
+
- bin/phare
|
6
|
+
|
7
|
+
Documentation:
|
8
|
+
Enabled: false
|
9
|
+
|
10
|
+
Encoding:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
LineLength:
|
14
|
+
Max: 200
|
15
|
+
|
16
|
+
AccessModifierIndentation:
|
17
|
+
EnforcedStyle: outdent
|
18
|
+
|
19
|
+
IfUnlessModifier:
|
20
|
+
Enabled: false
|
21
|
+
|
22
|
+
CaseIndentation:
|
23
|
+
IndentWhenRelativeTo: case
|
24
|
+
IndentOneStep: true
|
25
|
+
|
26
|
+
MethodLength:
|
27
|
+
CountComments: false
|
28
|
+
Max: 20
|
29
|
+
|
30
|
+
SignalException:
|
31
|
+
Enabled: false
|
32
|
+
|
33
|
+
ColonMethodCall:
|
34
|
+
Enabled: false
|
35
|
+
|
36
|
+
AsciiComments:
|
37
|
+
Enabled: false
|
38
|
+
|
39
|
+
Lambda:
|
40
|
+
Enabled: false
|
41
|
+
|
42
|
+
RegexpLiteral:
|
43
|
+
Enabled: false
|
44
|
+
|
45
|
+
AssignmentInCondition:
|
46
|
+
Enabled: false
|
47
|
+
|
48
|
+
Metrics/AbcSize:
|
49
|
+
Enabled: false
|
50
|
+
|
51
|
+
ClassLength:
|
52
|
+
Enabled: false
|
data/README.md
CHANGED
@@ -1,8 +1,16 @@
|
|
1
1
|
## Introduction
|
2
2
|
|
3
|
-
Aigu
|
4
|
-
|
5
|
-
|
3
|
+
Aigu is a set of utility to process localization files to genarate JSON files
|
4
|
+
to push to Accent service. Pulling from Accent to update localization files
|
5
|
+
is also supported.
|
6
|
+
|
7
|
+
The following localization file formats are supported: Rails YAML, Android
|
8
|
+
XML, Java Enum Core, iOS strings and stringsdict.
|
9
|
+
|
10
|
+
Merge and unmerge commands allows to merge different source files into a
|
11
|
+
single JSON file to send as a single Accent project.
|
12
|
+
|
13
|
+
Push and pull can be used to interact directly with Accent.
|
6
14
|
|
7
15
|
## Installation
|
8
16
|
|
@@ -36,6 +44,13 @@ $ aigu export --locale=fr --input-directory=config/locales --output-file=my-proj
|
|
36
44
|
| `output-file` | The path to the JSON file that will be written by `aigu` |
|
37
45
|
| `ignore` | The patterns `aigu` will use to skip ignored files (eg. `routes.yml`)
|
38
46
|
|
47
|
+
| Command | File format |
|
48
|
+
|-------------------|-------------------------------------------------------|
|
49
|
+
| `export` | Rails YAML |
|
50
|
+
| `andoird_export` | Android XML |
|
51
|
+
| `core_export` | Java Enum Core |
|
52
|
+
| `ios_export` | iOS strings & stringsdict |
|
53
|
+
|
39
54
|
### Importing the JSON file from Accent
|
40
55
|
|
41
56
|
The `import` command takes a generated JSON file from Accent and generates
|
@@ -53,10 +68,67 @@ $ aigu import --locale=fr --input-file=file-from-accent.json --output-directory=
|
|
53
68
|
| `input-file` | The path to the Accent-generated JSON file |
|
54
69
|
| `output-directory` | The directory where the localization YAML files will be generated |
|
55
70
|
|
56
|
-
|
71
|
+
| Command | File format |
|
72
|
+
|-------------------|-------------------------------------------------------|
|
73
|
+
| `import` | Rails YAML |
|
74
|
+
| `andoird_import` | Android XML |
|
75
|
+
| `core_import` | Java Enum Core |
|
76
|
+
| `ios_import` | iOS strings & stringsdict |
|
77
|
+
|
78
|
+
### Merge
|
79
|
+
|
80
|
+
The `merge` command will combine several JSON file into a single one to send into a single Accent project. It will prefix keys with
|
81
|
+
a pattern embedding the filename to allow later unmerging. It works from an input directory, mergin all json files in it.
|
82
|
+
A file can be named `default.json` to avoid prefixes in the resulting json.
|
83
|
+
|
84
|
+
#### Options
|
85
|
+
|
86
|
+
| Option | Description |
|
87
|
+
|--------------------|---------------------------------------------------------------------------------------------------|
|
88
|
+
| `input-directory` | The directory containing json files to merge |
|
89
|
+
| `output-file` | The path to the JSON file that will be written to |
|
90
|
+
|
91
|
+
|
92
|
+
### Unmerge
|
93
|
+
|
94
|
+
The `unmerge` will split the Accent JSON file into several json files, for further processing. It will look for the prefix pattern
|
95
|
+
of the merge command and will extract the filename or use default.json if pattern is not found.
|
96
|
+
|
97
|
+
#### Options
|
98
|
+
|
99
|
+
| Option | Description |
|
100
|
+
|--------------------|---------------------------------------------------------------------------------------------------|
|
101
|
+
| `input-file` | The path to the Accent-generated JSON file |
|
102
|
+
| `output-directory` | The directory where the unmerged files will be written |
|
103
|
+
|
104
|
+
### Sending to Accent
|
105
|
+
|
106
|
+
The `push` command takes a JSON file exported by Aigu and send it to Accent
|
107
|
+
|
108
|
+
#### Options
|
109
|
+
|
110
|
+
| Option | Description |
|
111
|
+
|--------------------|---------------------------------------------------------------------------------------------------|
|
112
|
+
| `input-file` | The path to the Aigu-generated JSON file |
|
113
|
+
| `accent-api-key` | The API key of the Accent project. (See project config in Accent) |
|
114
|
+
| `accent-url` | The URL to the instance of Accent to use (Prod: http://accent.mirego.com, QA: https://mirego-accent-qa.herokuapp.com ) |
|
115
|
+
|
116
|
+
### Pulling from Accent
|
117
|
+
|
118
|
+
The `pull` command GET the Accent generated JSON file
|
119
|
+
|
120
|
+
#### Options
|
121
|
+
|
122
|
+
| Option | Description |
|
123
|
+
|--------------------|---------------------------------------------------------------------------------------------------|
|
124
|
+
| `output-file` | The path to write the Accent JSON file to |
|
125
|
+
| `accent-api-key` | The API key of the Accent project. (See project config in Accent) |
|
126
|
+
| `accent-url` | The URL to the instance of Accent to use (Prod: http://accent.mirego.com, QA: https://mirego-accent-qa.herokuapp.com ) |
|
127
|
+
|
128
|
+
### Using `.aigu.yml`
|
57
129
|
|
58
130
|
Instead of using command-line arguments when running the `aigu` command, you
|
59
|
-
can create a
|
131
|
+
can create a `.aigu.yml` file at the root of your project and hard-code options
|
60
132
|
in that file.
|
61
133
|
|
62
134
|
```yaml
|
@@ -67,6 +139,18 @@ output-directory: config/locales
|
|
67
139
|
input-directory: config/locales
|
68
140
|
```
|
69
141
|
|
142
|
+
## Contributing
|
143
|
+
|
144
|
+
We’re using `phare` to make sure all Ruby code adheres to our coding style
|
145
|
+
guide. The best way to use `phare` is as a pre-commit hook:
|
146
|
+
|
147
|
+
```bash
|
148
|
+
$ ln -s "`pwd`/bin/phare" .git/hooks/pre-commit
|
149
|
+
```
|
150
|
+
|
151
|
+
That way, whenever `git commit` is ran, `phare` will be executed and will abort
|
152
|
+
the commit if there are errors.
|
153
|
+
|
70
154
|
## License
|
71
155
|
|
72
156
|
`Aigu` is © 2014 [Mirego](http://www.mirego.com) and may be freely distributed under the [New BSD license](http://opensource.org/licenses/BSD-3-Clause). See the [`LICENSE.md`](https://github.com/mirego/aigu/blob/master/LICENSE.md) file.
|
data/Rakefile
CHANGED
data/aigu.gemspec
CHANGED
@@ -6,19 +6,22 @@ require 'aigu/version'
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = 'aigu'
|
8
8
|
spec.version = Aigu::VERSION
|
9
|
-
spec.authors = ['Rémi Prévost']
|
10
|
-
spec.email = ['rprevost@mirego.com']
|
9
|
+
spec.authors = ['Rémi Prévost', 'William Jobin']
|
10
|
+
spec.email = ['rprevost@mirego.com', 'wjobin@mirego.com']
|
11
11
|
spec.description = 'Aigu converts a directory of Rails localization files into a single JSON file to import in Accent.'
|
12
12
|
spec.summary = spec.description
|
13
13
|
spec.homepage = 'https://github.com/mirego/aigu'
|
14
14
|
spec.license = 'BSD 3-Clause'
|
15
15
|
|
16
16
|
spec.files = `git ls-files`.split($/)
|
17
|
-
spec.executables =
|
17
|
+
spec.executables = 'aigu'
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
21
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
22
22
|
spec.add_development_dependency 'rake'
|
23
|
-
spec.add_development_dependency 'rspec', '~> 3.0
|
23
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
24
|
+
spec.add_development_dependency 'phare', '~> 0.6'
|
25
|
+
spec.add_development_dependency 'rubocop', '~> 0.27.0'
|
26
|
+
spec.add_development_dependency 'nokogiri', '~> 1.6.3'
|
24
27
|
end
|
data/bin/aigu
CHANGED
data/bin/phare
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This file was generated by Bundler.
|
4
|
+
#
|
5
|
+
# The application 'phare' is installed as part of a gem, and
|
6
|
+
# this file is here to facilitate running it.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
|
11
|
+
Pathname.new(__FILE__).realpath)
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'bundler/setup'
|
15
|
+
|
16
|
+
load Gem.bin_path('phare', 'phare')
|
data/lib/aigu.rb
CHANGED
@@ -4,11 +4,22 @@ require 'optparse'
|
|
4
4
|
require 'fileutils'
|
5
5
|
require 'json'
|
6
6
|
require 'yaml'
|
7
|
+
require 'nokogiri'
|
7
8
|
|
8
9
|
require 'aigu/extensions/hash'
|
9
10
|
require 'aigu/cli'
|
10
11
|
require 'aigu/importer'
|
11
12
|
require 'aigu/exporter'
|
13
|
+
require 'aigu/android_exporter'
|
14
|
+
require 'aigu/android_importer'
|
15
|
+
require 'aigu/core_exporter'
|
16
|
+
require 'aigu/core_importer'
|
17
|
+
require 'aigu/ios_exporter'
|
18
|
+
require 'aigu/ios_importer'
|
19
|
+
require 'aigu/unmergeer'
|
20
|
+
require 'aigu/mergeer'
|
21
|
+
require 'aigu/puller'
|
22
|
+
require 'aigu/pusher'
|
12
23
|
|
13
24
|
module Aigu
|
14
25
|
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
module Aigu
|
2
|
+
class AndroidExporter
|
3
|
+
def initialize(opts = {})
|
4
|
+
@output_file = opts[:'output-file']
|
5
|
+
@input_directory = opts[:'input-directory']
|
6
|
+
@locale = opts[:locale]
|
7
|
+
@ignore = opts[:ignore]
|
8
|
+
end
|
9
|
+
|
10
|
+
def process!
|
11
|
+
puts "Generating Accent JSON file `#{@output_file}` based on Android resources files in `#{@input_directory}` directory"
|
12
|
+
|
13
|
+
if @ignore
|
14
|
+
print 'Ignoring '
|
15
|
+
puts @ignore.join(', ')
|
16
|
+
end
|
17
|
+
|
18
|
+
puts '---'
|
19
|
+
|
20
|
+
build_output
|
21
|
+
write_json_file
|
22
|
+
|
23
|
+
puts '---'
|
24
|
+
puts 'Done'
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
def build_output
|
30
|
+
@output = {}
|
31
|
+
|
32
|
+
pattern = File.join(@input_directory, '*', 'strings.xml')
|
33
|
+
Dir[pattern].each do |filepath|
|
34
|
+
next unless supported_resource_for_language?(filepath, @locale)
|
35
|
+
|
36
|
+
if ignored_filepath?(filepath)
|
37
|
+
puts "Ignoring #{filepath}"
|
38
|
+
else
|
39
|
+
puts "Processing #{filepath}"
|
40
|
+
|
41
|
+
_, _, qualifiers = get_resource_type(filepath)
|
42
|
+
puts "Qualifiers: #{qualifiers}"
|
43
|
+
|
44
|
+
content = File.open(filepath, 'r:bom|utf-8').read
|
45
|
+
base_key = qualifiers
|
46
|
+
|
47
|
+
content = parse_xml(content, base_key)
|
48
|
+
@output.merge! content
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
@output
|
53
|
+
end
|
54
|
+
|
55
|
+
def write_json_file
|
56
|
+
file_path = @output_file
|
57
|
+
puts "Generating #{file_path}"
|
58
|
+
FileUtils.mkdir_p(File.dirname(file_path))
|
59
|
+
|
60
|
+
File.open(file_path, 'w+') do |file|
|
61
|
+
file << JSON.pretty_generate(JSON.parse(@output.to_json))
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def sanitize_value_to_string(value)
|
66
|
+
case value
|
67
|
+
when true
|
68
|
+
'___TRUE___'
|
69
|
+
when false
|
70
|
+
'___FALSE___'
|
71
|
+
when nil
|
72
|
+
'___NULL___'
|
73
|
+
else
|
74
|
+
value
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def parse_xml(xml, base_key = '')
|
79
|
+
xml = cleanup_input_xml(xml)
|
80
|
+
doc = Nokogiri::XML(xml) { |config| config.options = Nokogiri::XML::ParseOptions::RECOVER }
|
81
|
+
resources = doc.root.children
|
82
|
+
string_hash = {}
|
83
|
+
|
84
|
+
resources.each do |node|
|
85
|
+
if node.name == 'string'
|
86
|
+
string_hash.merge!(hash_for_key_value(node['name'], node.content, base_key))
|
87
|
+
elsif node.name == 'string-array'
|
88
|
+
resource_string_prefix = node['name'] + '__ARRAY_ITEM__#'
|
89
|
+
|
90
|
+
item_index = 0
|
91
|
+
node.children.each do |array_item|
|
92
|
+
next unless array_item.name == 'item'
|
93
|
+
|
94
|
+
hash = hash_for_key_value("#{resource_string_prefix}#{item_index}", array_item.content, base_key)
|
95
|
+
string_hash.merge! hash
|
96
|
+
|
97
|
+
item_index += 1
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
string_hash
|
103
|
+
end
|
104
|
+
|
105
|
+
def build_key_name(key_name, base_key)
|
106
|
+
base_key.empty? ? key_name : "#{key_name}__@TYPE_#{base_key}"
|
107
|
+
end
|
108
|
+
|
109
|
+
def hash_for_key_value(key, value, base_key)
|
110
|
+
{ build_key_name(key, base_key) => value }
|
111
|
+
end
|
112
|
+
|
113
|
+
# Try to fix issue
|
114
|
+
def cleanup_input_xml(xml)
|
115
|
+
replace_html_name(xml, 'quot', '"')
|
116
|
+
replace_html_name(xml, 'amp', '&')
|
117
|
+
replace_html_name(xml, 'apos', "'")
|
118
|
+
replace_html_name(xml, 'lt', '<')
|
119
|
+
replace_html_name(xml, 'gt', '>')
|
120
|
+
xml
|
121
|
+
end
|
122
|
+
|
123
|
+
def replace_html_name(xml, html_name, character)
|
124
|
+
replace_string = "&##{character.ord};"
|
125
|
+
xml.gsub!(/&#{html_name};/, replace_string)
|
126
|
+
end
|
127
|
+
|
128
|
+
# Parse out resource meta from filename
|
129
|
+
# Assumes first qualifer is locale if 2 chars
|
130
|
+
def get_resource_type(filepath)
|
131
|
+
filepath_parts = filepath.split(File::SEPARATOR)
|
132
|
+
filepath = filepath_parts[-2]
|
133
|
+
|
134
|
+
resource_qualifiers = filepath.split('-')
|
135
|
+
|
136
|
+
resource_type, first_qualifier = resource_qualifiers
|
137
|
+
|
138
|
+
first_qualifier_is_locale = !first_qualifier || (first_qualifier.length == 2)
|
139
|
+
|
140
|
+
if first_qualifier_is_locale
|
141
|
+
resource_qualifiers.shift(2)
|
142
|
+
locale = first_qualifier
|
143
|
+
else
|
144
|
+
resource_qualifiers.shift(1)
|
145
|
+
locale = nil
|
146
|
+
end
|
147
|
+
|
148
|
+
[resource_type, locale, resource_qualifiers.join(' ')]
|
149
|
+
end
|
150
|
+
|
151
|
+
def supported_resource_for_language?(filepath, expected_locale)
|
152
|
+
_, locale = get_resource_type(filepath)
|
153
|
+
expected_locale == locale
|
154
|
+
end
|
155
|
+
|
156
|
+
def ignored_filepath?(filepath)
|
157
|
+
@ignore && @ignore.any? do |pattern|
|
158
|
+
File.fnmatch(pattern, filepath, File::FNM_PATHNAME | File::FNM_DOTMATCH)
|
159
|
+
end
|
160
|
+
|
161
|
+
_, locale = get_resource_type(filepath)
|
162
|
+
!(@locale == locale)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
module Aigu
|
2
|
+
class AndroidImporter
|
3
|
+
ARRAY_REGEX = /__ARRAY_ITEM__#(?<index>\d+)$/
|
4
|
+
TYPE_REGEX = /__@TYPE_(?<type_key>.+)$/
|
5
|
+
|
6
|
+
def initialize(opts = {})
|
7
|
+
@input_file = opts[:'input-file']
|
8
|
+
@output_directory = opts[:'output-directory']
|
9
|
+
@locale = opts[:locale]
|
10
|
+
end
|
11
|
+
|
12
|
+
def process!
|
13
|
+
puts "Generating Android XML files in `#{@output_directory}` based on Accent-generated `#{@input_file}` file"
|
14
|
+
puts '---'
|
15
|
+
|
16
|
+
parse_json
|
17
|
+
@blob = split_res_types(@object)
|
18
|
+
write_xml_files
|
19
|
+
|
20
|
+
puts '---'
|
21
|
+
puts 'Done'
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
def parse_json
|
27
|
+
json = File.read(@input_file)
|
28
|
+
@object = JSON.parse(json)
|
29
|
+
@object = expand_content_values(@object)
|
30
|
+
end
|
31
|
+
|
32
|
+
def write_xml_files
|
33
|
+
@blob.each_pair do |type, hash|
|
34
|
+
# TODO: add locale to filename
|
35
|
+
qualifier = type.gsub(/_/, '-')
|
36
|
+
if qualifier != ''
|
37
|
+
qualifier.prepend('-')
|
38
|
+
end
|
39
|
+
if @locale
|
40
|
+
language = '-' + @locale
|
41
|
+
else
|
42
|
+
language = ''
|
43
|
+
end
|
44
|
+
|
45
|
+
file_path = File.join(@output_directory, "values#{language}#{qualifier}", 'strings.xml')
|
46
|
+
puts "Generating #{file_path}"
|
47
|
+
FileUtils.mkdir_p(File.dirname(file_path))
|
48
|
+
|
49
|
+
File.open(file_path, 'w+:bom|utf-8') do |file|
|
50
|
+
file << res_to_xml(hash)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# TODO: Use XML tooling
|
56
|
+
def res_to_xml(content)
|
57
|
+
xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
|
58
|
+
xml << "<resources>\n"
|
59
|
+
|
60
|
+
content.each_pair do |key, value|
|
61
|
+
if value.is_a?(Array)
|
62
|
+
xml << ' <string-array name=' << key.encode(xml: :attr) << ">\n"
|
63
|
+
value.each do |item|
|
64
|
+
xml << ' <item>' << item.encode(xml: :text) << "</item>\n"
|
65
|
+
end
|
66
|
+
xml << " </string-array>\n"
|
67
|
+
elsif value.is_a?(String)
|
68
|
+
xml << ' <string name=' << key.encode(xml: :attr) << '>' << value.encode(xml: :text) << "</string>\n"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
xml << "</resources>\n"
|
73
|
+
xml
|
74
|
+
end
|
75
|
+
|
76
|
+
def localize_content_keys(content)
|
77
|
+
content.reduce({}) do |memo, (key, value)|
|
78
|
+
localized_key = key.gsub(/^([^|]+)\|/, "\\1.#{@locale}|#{@locale}.")
|
79
|
+
memo.merge localized_key => value
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def expand_content_values(content)
|
84
|
+
content.each_with_object({}) do |(key, value), memo|
|
85
|
+
match_data = key.match(ARRAY_REGEX)
|
86
|
+
|
87
|
+
if match_data
|
88
|
+
canonical_key = key.gsub(ARRAY_REGEX, '')
|
89
|
+
value_index = match_data[:index].to_i
|
90
|
+
memo[canonical_key] ||= []
|
91
|
+
memo[canonical_key][value_index] = sanitize_string_to_value(value)
|
92
|
+
else
|
93
|
+
memo[key] = sanitize_string_to_value(value)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def split_res_types(content)
|
99
|
+
res_types = {}
|
100
|
+
|
101
|
+
content.each_pair do |key, value|
|
102
|
+
match_data = key.match(TYPE_REGEX)
|
103
|
+
if match_data
|
104
|
+
canonical_key = key.gsub(TYPE_REGEX, '')
|
105
|
+
res_type = match_data[:type_key]
|
106
|
+
else
|
107
|
+
canonical_key = key
|
108
|
+
res_type = ''
|
109
|
+
end
|
110
|
+
res_types[res_type] ||= {}
|
111
|
+
res_types[res_type][canonical_key] = value
|
112
|
+
end
|
113
|
+
|
114
|
+
res_types
|
115
|
+
end
|
116
|
+
|
117
|
+
def sanitize_string_to_value(string)
|
118
|
+
case string
|
119
|
+
when '___TRUE___'
|
120
|
+
true
|
121
|
+
when '___FALSE___'
|
122
|
+
false
|
123
|
+
when '___NULL___'
|
124
|
+
nil
|
125
|
+
else
|
126
|
+
string
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|