ios_polyglot_cli 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|