ios_polyglot_cli 2.0.1
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/.gitignore +129 -0
- data/.ruby-version +1 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +91 -0
- data/LICENSE +21 -0
- data/README.md +63 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/polyglot +41 -0
- data/ios-polyglot-cli.gemspec +35 -0
- data/lib/ios_polyglot_cli/api/base.rb +19 -0
- data/lib/ios_polyglot_cli/api/language.rb +20 -0
- data/lib/ios_polyglot_cli/api/project.rb +7 -0
- data/lib/ios_polyglot_cli/api/session.rb +9 -0
- data/lib/ios_polyglot_cli/api/translation.rb +8 -0
- data/lib/ios_polyglot_cli/api/translation_key.rb +24 -0
- data/lib/ios_polyglot_cli/commands/login.rb +32 -0
- data/lib/ios_polyglot_cli/commands/pull.rb +81 -0
- data/lib/ios_polyglot_cli/commands/setup.rb +80 -0
- data/lib/ios_polyglot_cli/error_handler.rb +28 -0
- data/lib/ios_polyglot_cli/helpers/depaginate.rb +18 -0
- data/lib/ios_polyglot_cli/helpers/general.rb +79 -0
- data/lib/ios_polyglot_cli/helpers/terminal.rb +17 -0
- data/lib/ios_polyglot_cli/io/config.rb +20 -0
- data/lib/ios_polyglot_cli/io/token.rb +25 -0
- data/lib/ios_polyglot_cli/serializers/languages/languages_serializer.rb +27 -0
- data/lib/ios_polyglot_cli/serializers/languages/languages_serializer_objc.rb +90 -0
- data/lib/ios_polyglot_cli/serializers/languages/languages_serializer_swift.rb +41 -0
- data/lib/ios_polyglot_cli/serializers/sources/sources_serializer_swift.rb +63 -0
- data/lib/ios_polyglot_cli/serializers/sources/swift_helpers/translation_case.rb +23 -0
- data/lib/ios_polyglot_cli/serializers/sources/swift_helpers/translation_enum.rb +84 -0
- data/lib/ios_polyglot_cli/serializers/translations/translations_serializer.rb +33 -0
- data/lib/ios_polyglot_cli/version.rb +3 -0
- data/lib/ios_polyglot_cli.rb +42 -0
- metadata +192 -0
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'commander/blank'
|
2
|
+
require 'commander/command'
|
3
|
+
|
4
|
+
module PolyglotIos
|
5
|
+
module Command
|
6
|
+
class Setup
|
7
|
+
include Helper::Terminal
|
8
|
+
include Helper::General
|
9
|
+
|
10
|
+
def self.init(options = Commander::Command::Options.new)
|
11
|
+
new(options).call
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(options = Commander::Command::Options.new)
|
15
|
+
@options = options
|
16
|
+
end
|
17
|
+
|
18
|
+
def call
|
19
|
+
project_id = project_id_prompt
|
20
|
+
language = language_prompt
|
21
|
+
translations_path = translations_path_prompt
|
22
|
+
sources_path = sources_path_prompt
|
23
|
+
project = {
|
24
|
+
id: project_id,
|
25
|
+
path: translations_path,
|
26
|
+
sourceFilesPath: sources_path
|
27
|
+
}
|
28
|
+
config = {
|
29
|
+
language: language,
|
30
|
+
projects: [project]
|
31
|
+
}
|
32
|
+
PolyglotIos::IO::Config.write(config)
|
33
|
+
success
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# Project ID
|
39
|
+
|
40
|
+
def project_id_prompt
|
41
|
+
prompt.select('Choose a project: ', filtered_projects)
|
42
|
+
end
|
43
|
+
|
44
|
+
def projects
|
45
|
+
prompt.say('Getting projects...')
|
46
|
+
PolyglotIos::Resource::Project.token(token).depaginate.each_with_object({}) do |r, hash|
|
47
|
+
hash[r.name] = r.id
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def filtered_projects
|
52
|
+
projects.select { |key, _id| key[/^(.*?(#{option_query})[^$]*)$/i] }.sort_by { |p| p[0].downcase }.to_h
|
53
|
+
end
|
54
|
+
|
55
|
+
def option_query
|
56
|
+
@option_query ||= @options.__hash__.fetch(:query, '')
|
57
|
+
end
|
58
|
+
|
59
|
+
# Language
|
60
|
+
|
61
|
+
def language_prompt
|
62
|
+
languages = {'Swift' => 'swift', 'Objective-C' => 'objc'}
|
63
|
+
prompt.select('Choose a language: ', languages)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Translations path
|
67
|
+
|
68
|
+
def translations_path_prompt
|
69
|
+
prompt.ask('Where would you like to store translation files (.strings)?', default: './Resources/Translations/')
|
70
|
+
end
|
71
|
+
|
72
|
+
# Sources path
|
73
|
+
|
74
|
+
def sources_path_prompt
|
75
|
+
prompt.ask('Where would you like to store source files?', default: './Common/Translations/')
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module PolyglotIos
|
2
|
+
class ErrorHandler
|
3
|
+
extend Helper::Terminal
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def rescuable
|
7
|
+
yield
|
8
|
+
rescue => e
|
9
|
+
handle(e)
|
10
|
+
end
|
11
|
+
|
12
|
+
def handle(e)
|
13
|
+
prompt.error(
|
14
|
+
case e
|
15
|
+
when JsonApiClient::Errors::NotAuthorized
|
16
|
+
"You are not authorized. Please call `polyglot login` and provide correct credentials."
|
17
|
+
when JsonApiClient::Errors::AccessDenied
|
18
|
+
"You don't have the permission to access requested project."
|
19
|
+
when Errno::ENOENT
|
20
|
+
"We could not find a file that we need:\n\n#{e.message}"
|
21
|
+
else
|
22
|
+
"An error happened. This might help:\n\n#{e.message}"
|
23
|
+
end
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module PolyglotIos
|
2
|
+
module Helper
|
3
|
+
module Depaginate
|
4
|
+
PER_PAGE = 100
|
5
|
+
|
6
|
+
def depaginate_query(query)
|
7
|
+
depaginated_array = []
|
8
|
+
page = query.page(1).per(PER_PAGE).all
|
9
|
+
until page.nil?
|
10
|
+
depaginated_array += page
|
11
|
+
page = page.pages.next
|
12
|
+
end
|
13
|
+
depaginated_array
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module PolyglotIos
|
2
|
+
module Helper
|
3
|
+
module General
|
4
|
+
ESCAPE_KEYWORDS = ["associatedtype", "class", "deinit", "enum", "extension", "fileprivate", "func",
|
5
|
+
"import", "init", "inout", "internal", "let", "operator", "private", "protocol",
|
6
|
+
"public", "static", "struct", "subscript", "typealias", "var", "break", "case",
|
7
|
+
"continue", "default", "defer", "do", "else", "fallthrough", "for", "guard", "if",
|
8
|
+
"in", "repeat", "return", "switch", "where", "while", "as", "Any", "catch", "false",
|
9
|
+
"is", "nil", "rethrows", "super", "self", "Self", "throw", "throws", "true", "try", "_"]
|
10
|
+
def token
|
11
|
+
@token ||= PolyglotIos::IO::Token.read
|
12
|
+
if @token.to_s.empty?
|
13
|
+
PolyglotIos::Command::Login.init
|
14
|
+
@token = PolyglotIos::IO::Token.read
|
15
|
+
end
|
16
|
+
@token
|
17
|
+
end
|
18
|
+
|
19
|
+
def config
|
20
|
+
@config ||= PolyglotIos::IO::Config.read.with_indifferent_access
|
21
|
+
end
|
22
|
+
|
23
|
+
def project_configs
|
24
|
+
@project_configs ||= config[:projects]
|
25
|
+
end
|
26
|
+
|
27
|
+
def programming_language
|
28
|
+
@programming_language ||= config[:language]
|
29
|
+
end
|
30
|
+
|
31
|
+
def use_old_naming
|
32
|
+
@useOldNaming ||= config[:useOldNaming]
|
33
|
+
end
|
34
|
+
|
35
|
+
def indent(level = 0, initial = "")
|
36
|
+
(1..level)
|
37
|
+
.to_a.reduce("") { |result, value| result + " " }
|
38
|
+
.concat(initial)
|
39
|
+
end
|
40
|
+
|
41
|
+
def clean_enum_name(name)
|
42
|
+
clean_name = name
|
43
|
+
.split(/[^0-9a-zA-Z]/)
|
44
|
+
.reject { |c| c.empty? }
|
45
|
+
.map { |value| value.capitalize }
|
46
|
+
.join
|
47
|
+
|
48
|
+
escape_with_underscore_if_needed(clean_name)
|
49
|
+
end
|
50
|
+
|
51
|
+
def clean_case_name(name)
|
52
|
+
clean_variable_name(name)
|
53
|
+
end
|
54
|
+
|
55
|
+
def clean_variable_name(name)
|
56
|
+
clean_name = name
|
57
|
+
.split(/[^0-9a-zA-Z]/)
|
58
|
+
.reject { |c| c.empty? }
|
59
|
+
.each_with_index
|
60
|
+
.map { |value, index| index == 0 ? value.downcase : value.capitalize }
|
61
|
+
.join
|
62
|
+
|
63
|
+
escaped_underscore = escape_with_underscore_if_needed(clean_name)
|
64
|
+
escape_keyword_if_needed(escaped_underscore)
|
65
|
+
end
|
66
|
+
|
67
|
+
def escape_with_underscore_if_needed(name)
|
68
|
+
return name if name.match(/^[A-Za-z_]/)
|
69
|
+
"_" + name
|
70
|
+
end
|
71
|
+
|
72
|
+
def escape_keyword_if_needed(name)
|
73
|
+
return name if !ESCAPE_KEYWORDS.include? name
|
74
|
+
"`#{name}`"
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module PolyglotIos
|
2
|
+
module IO
|
3
|
+
class Config
|
4
|
+
|
5
|
+
CONFIG_FILE_PATH = "#{Dir.pwd}/polyglot.yml".freeze
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def write(data)
|
9
|
+
File.open(CONFIG_FILE_PATH, 'w') { |file| YAML.dump(data, file) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def read
|
13
|
+
YAML.load_file(CONFIG_FILE_PATH)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module PolyglotIos
|
2
|
+
module IO
|
3
|
+
class Token
|
4
|
+
|
5
|
+
KEYCHAIN_SERVICE = 'polyglot'.freeze
|
6
|
+
KEYCHAIN_TOKEN_KEY = 'polyglot_token'.freeze
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def write(token)
|
10
|
+
keychain[KEYCHAIN_SERVICE, KEYCHAIN_TOKEN_KEY] = token
|
11
|
+
end
|
12
|
+
|
13
|
+
def read
|
14
|
+
keychain[KEYCHAIN_SERVICE, KEYCHAIN_TOKEN_KEY]
|
15
|
+
end
|
16
|
+
|
17
|
+
def keychain
|
18
|
+
@keychain ||= OSXKeychain.new
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module PolyglotIos
|
2
|
+
module Serializer
|
3
|
+
module Language
|
4
|
+
class Base
|
5
|
+
include ERB::Util
|
6
|
+
attr_accessor :languages
|
7
|
+
|
8
|
+
def initialize(languages)
|
9
|
+
@languages = languages
|
10
|
+
end
|
11
|
+
|
12
|
+
def render()
|
13
|
+
ERB.new(template, nil, '-').result(binding)
|
14
|
+
end
|
15
|
+
|
16
|
+
def template()
|
17
|
+
fail NotImplementedError, 'Abstract Method'
|
18
|
+
end
|
19
|
+
|
20
|
+
def save(path)
|
21
|
+
fail NotImplementedError, 'Abstract Method'
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require_relative 'languages_serializer'
|
2
|
+
|
3
|
+
module PolyglotIos
|
4
|
+
module Serializer
|
5
|
+
module Language
|
6
|
+
class ObjC < Base
|
7
|
+
|
8
|
+
def render()
|
9
|
+
h_file = ERB.new(h_template, nil, '-').result(binding)
|
10
|
+
m_file = ERB.new(m_template, nil, '-').result(binding)
|
11
|
+
return h_file, m_file
|
12
|
+
end
|
13
|
+
|
14
|
+
def save(sources_path)
|
15
|
+
FileUtils.mkdir_p sources_path unless File.exist? sources_path
|
16
|
+
h_file, m_file = render()
|
17
|
+
File.write(File.join(sources_path, "Language.h"), h_file)
|
18
|
+
File.write(File.join(sources_path, "Language.m"), m_file)
|
19
|
+
end
|
20
|
+
|
21
|
+
def h_template()
|
22
|
+
<<-H_TEMPLATE
|
23
|
+
#import <Foundation/Foundation.h>
|
24
|
+
|
25
|
+
@interface Language : NSObject
|
26
|
+
|
27
|
+
@property (nonatomic, strong, readonly) NSString *name;
|
28
|
+
@property (nonatomic, strong, readonly) NSString *localName;
|
29
|
+
@property (nonatomic, strong, readonly) NSString *locale;
|
30
|
+
@property (nonatomic, strong, readonly) NSString *languageCode;
|
31
|
+
|
32
|
+
@property (readonly, class) NSArray<Language *> *allLanguages;
|
33
|
+
<% @languages.each do |language| -%>
|
34
|
+
@property (readonly, class) Language *<%= language.clean_name %>;
|
35
|
+
<% end -%>
|
36
|
+
|
37
|
+
@end
|
38
|
+
H_TEMPLATE
|
39
|
+
end
|
40
|
+
|
41
|
+
def m_template()
|
42
|
+
<<-M_TEMPLATE
|
43
|
+
#import "Language.h"
|
44
|
+
|
45
|
+
@interface Language()
|
46
|
+
|
47
|
+
@property (nonatomic, strong) NSString *name;
|
48
|
+
@property (nonatomic, strong) NSString *localName;
|
49
|
+
@property (nonatomic, strong) NSString *locale;
|
50
|
+
@property (nonatomic, strong) NSString *languageCode;
|
51
|
+
|
52
|
+
@end
|
53
|
+
|
54
|
+
@implementation Language
|
55
|
+
|
56
|
+
- (instancetype)initWithName:(NSString *)name localName:(NSString *)localName locale:(NSString *)locale languageCode:(NSString *)languageCode
|
57
|
+
{
|
58
|
+
if (self = [super init]) {
|
59
|
+
_name = name;
|
60
|
+
_localName = localName;
|
61
|
+
_locale = locale;
|
62
|
+
_languageCode = languageCode;
|
63
|
+
}
|
64
|
+
return self;
|
65
|
+
}
|
66
|
+
|
67
|
+
<% @languages.each do |language| -%>
|
68
|
+
+ (Language *)<%= language.clean_name %>
|
69
|
+
{
|
70
|
+
return [[Language alloc] initWithName:@"<%= language.name %>" localName:@"<%= language.local_name %>" locale:@"<%= language.locale %>" languageCode:@"<%= language.code %>"];
|
71
|
+
}
|
72
|
+
|
73
|
+
<% end -%>
|
74
|
+
+ (NSArray<Language *> *)allLanguages
|
75
|
+
{
|
76
|
+
return @[
|
77
|
+
<% @languages.each_with_index do |language, i| -%>
|
78
|
+
Language.<%= language.clean_name %><%= i == (@languages.size - 1) ? "" : "," %>
|
79
|
+
<% end -%>
|
80
|
+
];
|
81
|
+
}
|
82
|
+
|
83
|
+
@end
|
84
|
+
M_TEMPLATE
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative 'languages_serializer'
|
2
|
+
|
3
|
+
module PolyglotIos
|
4
|
+
module Serializer
|
5
|
+
module Language
|
6
|
+
class Swift < Base
|
7
|
+
|
8
|
+
def save(sources_path)
|
9
|
+
FileUtils.mkdir_p sources_path unless File.exist? sources_path
|
10
|
+
output_path = File.join(sources_path, "Language.swift")
|
11
|
+
File.write(output_path, render)
|
12
|
+
end
|
13
|
+
|
14
|
+
def template()
|
15
|
+
<<-TEMPLATE
|
16
|
+
import Foundation
|
17
|
+
|
18
|
+
public struct Language {
|
19
|
+
|
20
|
+
public let name: String
|
21
|
+
public let localName: String
|
22
|
+
public let locale: String
|
23
|
+
public let languageCode: String
|
24
|
+
|
25
|
+
<% @languages.each do |language| -%>
|
26
|
+
public static let <%= language.clean_name %> = Language(name: "<%= language.name %>", localName: "<%= language.local_name %>", locale: "<%= language.locale %>", languageCode: "<%= language.code %>")
|
27
|
+
<% end -%>
|
28
|
+
|
29
|
+
public static let all = [
|
30
|
+
<% @languages.each_with_index do |language, i| -%>
|
31
|
+
Language.<%= language.clean_name %><%= i == (@languages.size - 1) ? "" : "," %>
|
32
|
+
<% end -%>
|
33
|
+
]
|
34
|
+
|
35
|
+
}
|
36
|
+
TEMPLATE
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require_relative 'swift_helpers/translation_case'
|
2
|
+
require_relative 'swift_helpers/translation_enum'
|
3
|
+
|
4
|
+
module PolyglotIos
|
5
|
+
module Serializer
|
6
|
+
module Source
|
7
|
+
class Swift
|
8
|
+
include ERB::Util
|
9
|
+
|
10
|
+
def initialize(translation_keys)
|
11
|
+
@translation_keys = translation_keys
|
12
|
+
end
|
13
|
+
|
14
|
+
def render()
|
15
|
+
@root_enum = build_translations()
|
16
|
+
ERB.new(template, nil, '-').result(binding)
|
17
|
+
end
|
18
|
+
|
19
|
+
def template()
|
20
|
+
<<-TEMPLATE
|
21
|
+
import Foundation
|
22
|
+
|
23
|
+
<%= @root_enum.serialized() %>
|
24
|
+
public protocol StringsProtocol: RawRepresentable {
|
25
|
+
var localized: String { get }
|
26
|
+
func localized(with args: CVarArg...) -> String
|
27
|
+
}
|
28
|
+
|
29
|
+
public extension StringsProtocol where RawValue == String {
|
30
|
+
var localized: String {
|
31
|
+
return self.rawValue.localized
|
32
|
+
}
|
33
|
+
|
34
|
+
func localized(with args: CVarArg...) -> String {
|
35
|
+
return String(format: self.rawValue.localized, arguments: args)
|
36
|
+
}
|
37
|
+
}
|
38
|
+
TEMPLATE
|
39
|
+
end
|
40
|
+
|
41
|
+
def build_translations()
|
42
|
+
root_enum = TranslationEnum.new("Strings")
|
43
|
+
|
44
|
+
@translation_keys.each do |translation_key|
|
45
|
+
key_name = translation_key.name
|
46
|
+
next if key_name.nil?
|
47
|
+
components = key_name.split(".")
|
48
|
+
root_enum.insert(components, key_name)
|
49
|
+
end
|
50
|
+
|
51
|
+
return root_enum
|
52
|
+
end
|
53
|
+
|
54
|
+
def save(sources_path)
|
55
|
+
FileUtils.mkdir_p sources_path unless File.exist? sources_path
|
56
|
+
output_path = File.join(sources_path, "Strings.swift")
|
57
|
+
File.write(output_path, render)
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module PolyglotIos
|
2
|
+
module Serializer
|
3
|
+
module Source
|
4
|
+
class TranslationCase
|
5
|
+
include Helper::General
|
6
|
+
|
7
|
+
attr_accessor :name
|
8
|
+
attr_accessor :value
|
9
|
+
|
10
|
+
def initialize(name, value)
|
11
|
+
@name = name
|
12
|
+
@value = value
|
13
|
+
end
|
14
|
+
|
15
|
+
def serialized()
|
16
|
+
clean_name = clean_case_name(name)
|
17
|
+
"case #{clean_name} = \"#{value}\""
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require_relative 'translation_case'
|
2
|
+
|
3
|
+
module PolyglotIos
|
4
|
+
module Serializer
|
5
|
+
module Source
|
6
|
+
class TranslationEnum
|
7
|
+
include Helper::General
|
8
|
+
attr_accessor :name
|
9
|
+
attr_accessor :translations
|
10
|
+
attr_accessor :child_enums
|
11
|
+
|
12
|
+
def initialize(name)
|
13
|
+
@name = name
|
14
|
+
@translations = []
|
15
|
+
@child_enums = []
|
16
|
+
end
|
17
|
+
|
18
|
+
def insert(components, key_name)
|
19
|
+
if components.count > 1
|
20
|
+
insert_to_nested_enum(components, key_name)
|
21
|
+
elsif components.count == 1
|
22
|
+
translation_case = TranslationCase.new(components.first, key_name)
|
23
|
+
translations.push(translation_case)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def serialized(indent_level = 0)
|
28
|
+
output = indent(indent_level)
|
29
|
+
clean_name = clean_enum_name(name)
|
30
|
+
|
31
|
+
if translations.count == 0
|
32
|
+
# enum without any case statement cannot be RawRepresentable
|
33
|
+
output.concat("public enum #{clean_name} {\n")
|
34
|
+
else
|
35
|
+
output.concat("public enum #{clean_name}: String, StringsProtocol {\n")
|
36
|
+
end
|
37
|
+
|
38
|
+
translations
|
39
|
+
.sort_by { |translation| translation.name.downcase }
|
40
|
+
.each do |translation|
|
41
|
+
output
|
42
|
+
.concat(indent(indent_level + 1, translation.serialized()))
|
43
|
+
.concat("\n")
|
44
|
+
end
|
45
|
+
|
46
|
+
if translations.count > 0 && child_enums.count > 0
|
47
|
+
output.concat("\n")
|
48
|
+
end
|
49
|
+
|
50
|
+
serialized_enums = child_enums
|
51
|
+
.sort_by { |child_enum| child_enum.name.downcase }
|
52
|
+
.map { |child_enum| child_enum.serialized(indent_level + 1) }
|
53
|
+
.join("\n")
|
54
|
+
output.concat(serialized_enums)
|
55
|
+
|
56
|
+
output.concat(indent(indent_level, "}\n"))
|
57
|
+
return output
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def insert_to_nested_enum(components, key_name)
|
63
|
+
_components = components.clone
|
64
|
+
|
65
|
+
enum_name = _components.shift
|
66
|
+
nested_enum = nested_enum_with_name(enum_name)
|
67
|
+
|
68
|
+
if !nested_enum.nil?
|
69
|
+
nested_enum.insert(_components, key_name)
|
70
|
+
else
|
71
|
+
child = TranslationEnum.new(enum_name)
|
72
|
+
child.insert(_components, key_name)
|
73
|
+
@child_enums.push(child)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def nested_enum_with_name(name)
|
78
|
+
child_enums.find { |enum| enum.name == name }
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module PolyglotIos
|
2
|
+
module Serializer
|
3
|
+
class Translation
|
4
|
+
class << self
|
5
|
+
|
6
|
+
def write(translation_keys, language, translations_path, use_old_naming = false)
|
7
|
+
translations = extract_translations(translation_keys, language)
|
8
|
+
|
9
|
+
data = translations
|
10
|
+
.sort
|
11
|
+
.map { |key, value| "\"#{key}\" = \"#{value}\";" }
|
12
|
+
.join("\n")
|
13
|
+
.concat("\n")
|
14
|
+
|
15
|
+
FileUtils.mkdir_p translations_path unless File.exist? translations_path
|
16
|
+
locale_code = language.code(use_old_naming)
|
17
|
+
output_path = File.join(translations_path, "#{locale_code}.strings")
|
18
|
+
File.write(output_path, data)
|
19
|
+
end
|
20
|
+
|
21
|
+
def extract_translations(translation_keys, language)
|
22
|
+
translation_keys.each_with_object({}) do |translation_key, strings|
|
23
|
+
key_name = translation_key.name
|
24
|
+
next if key_name.nil?
|
25
|
+
strings[key_name] = translation_key.clean_translation(language)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# Parsing
|
2
|
+
require 'yaml'
|
3
|
+
require 'osx_keychain'
|
4
|
+
require 'erb'
|
5
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
6
|
+
|
7
|
+
# Helpers
|
8
|
+
require 'ios_polyglot_cli/helpers/depaginate'
|
9
|
+
require 'ios_polyglot_cli/helpers/terminal'
|
10
|
+
require 'ios_polyglot_cli/helpers/general'
|
11
|
+
|
12
|
+
# JSON API Resources
|
13
|
+
require 'json_api_client'
|
14
|
+
require 'ios_polyglot_cli/api/base'
|
15
|
+
require 'ios_polyglot_cli/api/language'
|
16
|
+
require 'ios_polyglot_cli/api/project'
|
17
|
+
require 'ios_polyglot_cli/api/session'
|
18
|
+
require 'ios_polyglot_cli/api/translation'
|
19
|
+
require 'ios_polyglot_cli/api/translation_key'
|
20
|
+
|
21
|
+
# File Accessors
|
22
|
+
require 'ios_polyglot_cli/io/token'
|
23
|
+
require 'ios_polyglot_cli/io/config'
|
24
|
+
|
25
|
+
# Serializers
|
26
|
+
require 'ios_polyglot_cli/serializers/translations/translations_serializer'
|
27
|
+
require 'ios_polyglot_cli/serializers/languages/languages_serializer_objc'
|
28
|
+
require 'ios_polyglot_cli/serializers/languages/languages_serializer_swift'
|
29
|
+
require 'ios_polyglot_cli/serializers/sources/sources_serializer_swift'
|
30
|
+
|
31
|
+
# Commands
|
32
|
+
require 'ios_polyglot_cli/commands/login'
|
33
|
+
require 'ios_polyglot_cli/commands/setup'
|
34
|
+
require 'ios_polyglot_cli/commands/pull'
|
35
|
+
|
36
|
+
# Error Handler
|
37
|
+
require 'ios_polyglot_cli/error_handler'
|
38
|
+
require 'ios_polyglot_cli/version'
|
39
|
+
|
40
|
+
module PolyglotIos
|
41
|
+
|
42
|
+
end
|