ad_localize 4.1.1 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +6 -3
- data/.rubocop.yml +5 -0
- data/.rubocop_todo.yml +319 -0
- data/CHANGELOG.md +70 -15
- data/Gemfile +1 -0
- data/Gemfile.lock +63 -61
- data/README.md +37 -10
- data/Rakefile +1 -0
- data/ad_localize.gemspec +14 -13
- data/bin/console +1 -1
- data/exe/ad_localize +2 -1
- data/lib/ad_localize/ad_logger.rb +5 -10
- data/lib/ad_localize/cli.rb +10 -3
- data/lib/ad_localize/entities/key.rb +3 -76
- data/lib/ad_localize/entities/locale_wording.rb +32 -52
- data/lib/ad_localize/entities/platform.rb +13 -0
- data/lib/ad_localize/entities/simple_wording.rb +6 -0
- data/lib/ad_localize/entities/wording_type.rb +11 -0
- data/lib/ad_localize/interactors/base_generate_files.rb +37 -0
- data/lib/ad_localize/interactors/download_spreadsheets.rb +20 -0
- data/lib/ad_localize/interactors/export_wording.rb +27 -18
- data/lib/ad_localize/interactors/generate_info_plist.rb +24 -0
- data/lib/ad_localize/interactors/generate_ios_files.rb +12 -0
- data/lib/ad_localize/interactors/generate_json.rb +20 -0
- data/lib/ad_localize/interactors/generate_localizable_strings.rb +24 -0
- data/lib/ad_localize/interactors/generate_localizable_strings_dict.rb +24 -0
- data/lib/ad_localize/interactors/generate_properties.rb +20 -0
- data/lib/ad_localize/interactors/generate_strings.rb +25 -0
- data/lib/ad_localize/interactors/generate_yaml.rb +20 -0
- data/lib/ad_localize/interactors/merge_wordings.rb +49 -18
- data/lib/ad_localize/interactors/parse_csv_files.rb +22 -0
- data/lib/ad_localize/interactors/process_export_request.rb +21 -0
- data/lib/ad_localize/mappers/locale_wording_to_hash.rb +45 -24
- data/lib/ad_localize/mappers/options_to_export_request.rb +14 -21
- data/lib/ad_localize/option_handler.rb +50 -26
- data/lib/ad_localize/parsers/csv_parser.rb +84 -0
- data/lib/ad_localize/parsers/key_parser.rb +62 -0
- data/lib/ad_localize/repositories/drive_repository.rb +53 -0
- data/lib/ad_localize/repositories/file_system_repository.rb +2 -1
- data/lib/ad_localize/requests/export_request.rb +97 -53
- data/lib/ad_localize/sanitizers/ios_sanitizer.rb +12 -0
- data/lib/ad_localize/{mappers/android_translation_mapper.rb → sanitizers/ios_to_android_sanitizer.rb} +8 -8
- data/lib/ad_localize/sanitizers/pass_through_sanitizer.rb +10 -0
- data/lib/ad_localize/serializers/info_plist_serializer.rb +9 -11
- data/lib/ad_localize/serializers/json_serializer.rb +3 -5
- data/lib/ad_localize/serializers/localizable_strings_serializer.rb +9 -11
- data/lib/ad_localize/serializers/localizable_stringsdict_serializer.rb +12 -19
- data/lib/ad_localize/serializers/properties_serializer.rb +9 -11
- data/lib/ad_localize/serializers/strings_serializer.rb +12 -21
- data/lib/ad_localize/serializers/templated_serializer.rb +51 -0
- data/lib/ad_localize/serializers/yaml_serializer.rb +4 -6
- data/lib/ad_localize/templates/android/strings.xml.erb +6 -6
- data/lib/ad_localize/templates/ios/Localizable.stringsdict.erb +14 -14
- data/lib/ad_localize/version.rb +2 -1
- data/lib/ad_localize/view_models/compound_wording_view_model.rb +2 -0
- data/lib/ad_localize/view_models/simple_wording_view_model.rb +2 -0
- data/lib/ad_localize.rb +33 -34
- metadata +86 -69
- data/lib/ad_localize/constant.rb +0 -6
- data/lib/ad_localize/entities/translation.rb +0 -32
- data/lib/ad_localize/entities/wording.rb +0 -24
- data/lib/ad_localize/interactors/execute_export_request.rb +0 -43
- data/lib/ad_localize/interactors/export_csv_files.rb +0 -17
- data/lib/ad_localize/interactors/export_g_spreadsheet.rb +0 -59
- data/lib/ad_localize/interactors/platforms/export_android_locale_wording.rb +0 -43
- data/lib/ad_localize/interactors/platforms/export_csv_locale_wording.rb +0 -25
- data/lib/ad_localize/interactors/platforms/export_ios_locale_wording.rb +0 -66
- data/lib/ad_localize/interactors/platforms/export_json_locale_wording.rb +0 -27
- data/lib/ad_localize/interactors/platforms/export_platform_factory.rb +0 -50
- data/lib/ad_localize/interactors/platforms/export_properties_locale_wording.rb +0 -33
- data/lib/ad_localize/interactors/platforms/export_yaml_locale_wording.rb +0 -27
- data/lib/ad_localize/mappers/csv_path_to_wording.rb +0 -73
- data/lib/ad_localize/mappers/ios_translation_mapper.rb +0 -12
- data/lib/ad_localize/mappers/translation_group_mapper.rb +0 -14
- data/lib/ad_localize/mappers/translation_mapper.rb +0 -30
- data/lib/ad_localize/mappers/value_range_to_wording.rb +0 -67
- data/lib/ad_localize/repositories/g_sheets_repository.rb +0 -44
- data/lib/ad_localize/requests/g_spreadsheet_options.rb +0 -47
- data/lib/ad_localize/requests/merge_policy.rb +0 -28
- data/lib/ad_localize/serializers/with_template.rb +0 -19
- data/lib/ad_localize/validators/key_validator.rb +0 -31
- data/lib/ad_localize/view_models/translation_group_view_model.rb +0 -19
- data/lib/ad_localize/view_models/translation_view_model.rb +0 -23
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module AdLocalize
|
3
|
+
module Interactors
|
4
|
+
class BaseGenerateFiles
|
5
|
+
def initialize(serializer:)
|
6
|
+
@serializer = serializer
|
7
|
+
raise MissingArgument.new('Missing Serializer') unless serializer
|
8
|
+
|
9
|
+
@file_system_repository = Repositories::FileSystemRepository.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(wording:, export_request:)
|
13
|
+
wording.each do |locale, locale_wording|
|
14
|
+
next unless has_wording?(locale_wording: locale_wording)
|
15
|
+
|
16
|
+
path = output_path(locale_wording: locale_wording, export_request: export_request)
|
17
|
+
filename = path.basename
|
18
|
+
LOGGER.debug("[#{locale}] Generating #{filename}")
|
19
|
+
@file_system_repository.create_directory(path: path.dirname)
|
20
|
+
content = @serializer.render(locale_wording: locale_wording)
|
21
|
+
@file_system_repository.write(content: content, path: path)
|
22
|
+
LOGGER.debug("[#{locale}] #{filename} done !")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def has_wording?(locale_wording:)
|
29
|
+
raise 'override me!'
|
30
|
+
end
|
31
|
+
|
32
|
+
def output_path(locale_wording:, export_request:)
|
33
|
+
raise 'override me!'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module AdLocalize
|
3
|
+
module Interactors
|
4
|
+
class DownloadSpreadsheets
|
5
|
+
def initialize
|
6
|
+
@drive_repository = Repositories::DriveRepository.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(export_request:)
|
10
|
+
LOGGER.debug("Downloading spreadsheets")
|
11
|
+
if export_request.export_all
|
12
|
+
@drive_repository.download_all_sheets(spreadsheet_id: export_request.spreadsheet_id)
|
13
|
+
else
|
14
|
+
@drive_repository.download_sheets_by_id(spreadsheet_id: export_request.spreadsheet_id,
|
15
|
+
sheet_ids: export_request.sheet_ids)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,31 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module AdLocalize
|
2
3
|
module Interactors
|
3
4
|
class ExportWording
|
4
|
-
def initialize
|
5
|
-
@export_platform_factory = Platforms::ExportPlatformFactory.new
|
6
|
-
end
|
7
|
-
|
8
5
|
def call(export_request:, wording:)
|
9
|
-
LOGGER.debug("Starting export wording")
|
10
6
|
export_request.platforms.each do |platform|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
locales.each do |locale|
|
16
|
-
export_platform.call(wording: wording, locale: locale, platform_dir: platform_dir)
|
17
|
-
end
|
18
|
-
else
|
19
|
-
export_platform.call(export_request: export_request, platform_dir: platform_dir)
|
20
|
-
end
|
7
|
+
configure_output_directory(platform: platform, export_request: export_request)
|
8
|
+
LOGGER.debug("[#{platform}] Start exporting in #{export_request.output_dir}")
|
9
|
+
export_platform(wording: wording, platform: platform, export_request: export_request)
|
10
|
+
LOGGER.debug("[#{platform}] done !")
|
21
11
|
end
|
22
12
|
end
|
23
13
|
|
24
14
|
private
|
25
15
|
|
26
|
-
def
|
27
|
-
export_request.
|
16
|
+
def configure_output_directory(platform:, export_request:)
|
17
|
+
if export_request.many_platforms?
|
18
|
+
export_request.output_dir = export_request.output_path.join(platform)
|
19
|
+
else
|
20
|
+
export_request.output_dir = export_request.output_path
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def export_platform(wording:, platform:, export_request:)
|
25
|
+
case platform
|
26
|
+
when Entities::Platform::IOS
|
27
|
+
GenerateIOSFiles.new.call(wording: wording, export_request: export_request)
|
28
|
+
when Entities::Platform::ANDROID
|
29
|
+
GenerateStrings.new.call(wording: wording, export_request: export_request)
|
30
|
+
when Entities::Platform::YML
|
31
|
+
GenerateYAML.new.call(wording: wording, export_request: export_request)
|
32
|
+
when Entities::Platform::JSON
|
33
|
+
GenerateJSON.new.call(wording: wording, export_request: export_request)
|
34
|
+
when Entities::Platform::PROPERTIES
|
35
|
+
GenerateProperties.new.call(wording: wording, export_request: export_request)
|
36
|
+
end
|
28
37
|
end
|
29
38
|
end
|
30
39
|
end
|
31
|
-
end
|
40
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module AdLocalize
|
3
|
+
module Interactors
|
4
|
+
class GenerateInfoPlist < BaseGenerateFiles
|
5
|
+
INFO_PLIST_FILENAME = "InfoPlist.strings".freeze
|
6
|
+
LOCALE_DIRECTORY_CONVENTION = "%{locale}.lproj".freeze
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
super(serializer: Serializers::InfoPlistSerializer.new)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def has_wording?(locale_wording:)
|
15
|
+
locale_wording.info_plists.any?
|
16
|
+
end
|
17
|
+
|
18
|
+
def output_path(locale_wording:, export_request:)
|
19
|
+
locale_directory_name = LOCALE_DIRECTORY_CONVENTION % { locale: locale_wording.locale }
|
20
|
+
export_request.output_dir.join(locale_directory_name, INFO_PLIST_FILENAME)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module AdLocalize
|
3
|
+
module Interactors
|
4
|
+
class GenerateIOSFiles
|
5
|
+
def call(wording:, export_request:)
|
6
|
+
GenerateInfoPlist.new.call(wording: wording, export_request: export_request)
|
7
|
+
GenerateLocalizableStrings.new.call(wording: wording, export_request: export_request)
|
8
|
+
GenerateLocalizableStringsDict.new.call(wording: wording, export_request: export_request)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module AdLocalize
|
3
|
+
module Interactors
|
4
|
+
class GenerateJSON < BaseGenerateFiles
|
5
|
+
def initialize
|
6
|
+
super(serializer: Serializers::JSONSerializer.new)
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def has_wording?(locale_wording:)
|
12
|
+
locale_wording.singulars.any? || locale_wording.plurals.any?
|
13
|
+
end
|
14
|
+
|
15
|
+
def output_path(locale_wording:, export_request:)
|
16
|
+
export_request.output_dir.join("#{locale_wording.locale}.json")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module AdLocalize
|
3
|
+
module Interactors
|
4
|
+
class GenerateLocalizableStrings < BaseGenerateFiles
|
5
|
+
LOCALIZABLE_STRINGS_FILENAME = "Localizable.strings".freeze
|
6
|
+
LOCALE_DIRECTORY_CONVENTION = "%{locale}.lproj".freeze
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
super(serializer: Serializers::LocalizableStringsSerializer.new)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def has_wording?(locale_wording:)
|
15
|
+
locale_wording.singulars.any?
|
16
|
+
end
|
17
|
+
|
18
|
+
def output_path(locale_wording:, export_request:)
|
19
|
+
locale_directory_name = LOCALE_DIRECTORY_CONVENTION % { locale: locale_wording.locale }
|
20
|
+
export_request.output_dir.join(locale_directory_name, LOCALIZABLE_STRINGS_FILENAME)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module AdLocalize
|
3
|
+
module Interactors
|
4
|
+
class GenerateLocalizableStringsDict < BaseGenerateFiles
|
5
|
+
LOCALIZABLE_STRINGSDICT_FILENAME = "Localizable.stringsdict".freeze
|
6
|
+
LOCALE_DIRECTORY_CONVENTION = "%{locale}.lproj".freeze
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
super(serializer: Serializers::LocalizableStringsdictSerializer.new)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def has_wording?(locale_wording:)
|
15
|
+
locale_wording.plurals.any? || locale_wording.adaptives.any?
|
16
|
+
end
|
17
|
+
|
18
|
+
def output_path(locale_wording:, export_request:)
|
19
|
+
locale_directory_name = LOCALE_DIRECTORY_CONVENTION % { locale: locale_wording.locale }
|
20
|
+
export_request.output_dir.join(locale_directory_name, LOCALIZABLE_STRINGSDICT_FILENAME)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module AdLocalize
|
3
|
+
module Interactors
|
4
|
+
class GenerateProperties < BaseGenerateFiles
|
5
|
+
def initialize
|
6
|
+
super(serializer: Serializers::PropertiesSerializer.new)
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def has_wording?(locale_wording:)
|
12
|
+
locale_wording.singulars.any?
|
13
|
+
end
|
14
|
+
|
15
|
+
def output_path(locale_wording:, export_request:)
|
16
|
+
export_request.output_dir.join("#{locale_wording.locale}.properties")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module AdLocalize
|
3
|
+
module Interactors
|
4
|
+
class GenerateStrings < BaseGenerateFiles
|
5
|
+
STRINGS_FILENAME = 'strings.xml'.freeze
|
6
|
+
LOCALE_DIRECTORY_CONVENTION = "values".freeze
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
super(serializer: Serializers::StringsSerializer.new)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def has_wording?(locale_wording:)
|
15
|
+
locale_wording.singulars.any? || locale_wording.plurals.any?
|
16
|
+
end
|
17
|
+
|
18
|
+
def output_path(locale_wording:, export_request:)
|
19
|
+
locale_dir = LOCALE_DIRECTORY_CONVENTION
|
20
|
+
locale_dir += "-#{locale_wording.locale}" if !locale_wording.is_default
|
21
|
+
export_request.output_dir.join(locale_dir, STRINGS_FILENAME)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module AdLocalize
|
3
|
+
module Interactors
|
4
|
+
class GenerateYAML < BaseGenerateFiles
|
5
|
+
def initialize
|
6
|
+
super(serializer: Serializers::YAMLSerializer.new)
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def has_wording?(locale_wording:)
|
12
|
+
locale_wording.singulars.any? || locale_wording.plurals.any?
|
13
|
+
end
|
14
|
+
|
15
|
+
def output_path(locale_wording:, export_request:)
|
16
|
+
export_request.output_dir.join("#{locale_wording.locale}.yml")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,13 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module AdLocalize
|
2
3
|
module Interactors
|
3
4
|
class MergeWordings
|
4
5
|
REPLACE_MERGE_POLICY = 'replace'.freeze
|
5
6
|
KEEP_MERGE_POLICY = 'keep'.freeze
|
6
7
|
MERGE_POLICIES = [KEEP_MERGE_POLICY, REPLACE_MERGE_POLICY]
|
7
|
-
|
8
|
-
def self.valid_policy?(policy:)
|
9
|
-
MERGE_POLICIES.include?(policy)
|
10
|
-
end
|
8
|
+
DEFAULT_POLICY = KEEP_MERGE_POLICY
|
11
9
|
|
12
10
|
def call(wordings:, merge_policy:)
|
13
11
|
if wordings.size == 1
|
@@ -20,24 +18,57 @@ module AdLocalize
|
|
20
18
|
|
21
19
|
private
|
22
20
|
|
21
|
+
def merge_simple_wordings(reference_list:, new_list:, merge_policy:)
|
22
|
+
new_list.each do |label, new_translation|
|
23
|
+
translation_reference = reference_list[label]
|
24
|
+
if translation_reference.nil?
|
25
|
+
reference_list[label] = new_translation
|
26
|
+
elsif merge_policy == REPLACE_MERGE_POLICY
|
27
|
+
LOGGER.warn("[MERGE] #{label} value changed from #{translation_reference.value} to #{new_translation.value}")
|
28
|
+
reference_list[label].value = new_translation.value
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def merge_compound_wordings(reference_hash:, new_hash:, merge_policy:)
|
34
|
+
new_hash.each do |new_label, new_list|
|
35
|
+
if reference_hash[new_label].nil?
|
36
|
+
reference_hash[new_label] = new_list
|
37
|
+
elsif merge_policy == REPLACE_MERGE_POLICY
|
38
|
+
merge_simple_wordings(reference_list: reference_hash[new_label], new_list: new_list, merge_policy: merge_policy)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
23
43
|
def merge_many(wordings:, merge_policy:)
|
24
|
-
|
44
|
+
wording_reference = wordings.first
|
25
45
|
wordings[1..-1].each do |wording|
|
26
|
-
wording.
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
46
|
+
wording.each do |locale, locale_wording|
|
47
|
+
reference = wording_reference[locale]
|
48
|
+
merge_simple_wordings(
|
49
|
+
reference_list: reference.singulars,
|
50
|
+
new_list: locale_wording.singulars,
|
51
|
+
merge_policy: merge_policy
|
52
|
+
)
|
53
|
+
merge_simple_wordings(
|
54
|
+
reference_list: reference.info_plists,
|
55
|
+
new_list: locale_wording.info_plists,
|
56
|
+
merge_policy: merge_policy
|
57
|
+
)
|
58
|
+
merge_compound_wordings(
|
59
|
+
reference_hash: reference.plurals,
|
60
|
+
new_hash: locale_wording.plurals,
|
61
|
+
merge_policy: merge_policy
|
62
|
+
)
|
63
|
+
merge_compound_wordings(
|
64
|
+
reference_hash: reference.adaptives,
|
65
|
+
new_hash: locale_wording.adaptives,
|
66
|
+
merge_policy: merge_policy
|
67
|
+
)
|
37
68
|
end
|
38
69
|
end
|
39
|
-
|
70
|
+
wording_reference
|
40
71
|
end
|
41
72
|
end
|
42
73
|
end
|
43
|
-
end
|
74
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module AdLocalize
|
3
|
+
module Interactors
|
4
|
+
class ParseCSVFiles
|
5
|
+
def initialize
|
6
|
+
@csv_parser = Parsers::CSVParser.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(export_request:)
|
10
|
+
csv_paths = export_request.all_csv_paths
|
11
|
+
LOGGER.debug("Will parse #{csv_paths.size} csv files")
|
12
|
+
wordings = csv_paths.filter_map do |csv_path|
|
13
|
+
@csv_parser.call(csv_path: csv_path, export_request: export_request)
|
14
|
+
end
|
15
|
+
LOGGER.debug("#{wordings.size} wording contents detected")
|
16
|
+
return if wordings.blank?
|
17
|
+
|
18
|
+
MergeWordings.new.call(wordings: wordings, merge_policy: export_request.merge_policy)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module AdLocalize
|
3
|
+
module Interactors
|
4
|
+
class ProcessExportRequest
|
5
|
+
def call(export_request:)
|
6
|
+
export_request.verbose ? LOGGER.debug! : LOGGER.info!
|
7
|
+
LOGGER.debug(export_request)
|
8
|
+
LOGGER.debug("Verify if there are CSV to process")
|
9
|
+
return unless export_request.has_csv_paths?
|
10
|
+
|
11
|
+
LOGGER.debug("Parse CSV files")
|
12
|
+
wording = ParseCSVFiles.new.call(export_request: export_request)
|
13
|
+
return unless wording
|
14
|
+
|
15
|
+
LOGGER.debug("Export wording")
|
16
|
+
ExportWording.new.call(export_request: export_request, wording: wording)
|
17
|
+
LOGGER.debug("End of export request execution")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,33 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module AdLocalize
|
2
3
|
module Mappers
|
3
4
|
class LocaleWordingToHash
|
4
5
|
def map(locale_wording:)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
6
|
+
singulars_hash = map_singulars(simple_wordings: locale_wording.singulars.values)
|
7
|
+
plural_hash = map_plurals(coumpound_wordings: locale_wording.plurals)
|
8
|
+
locale_hash = singulars_hash.merge(plural_hash)
|
9
|
+
{ locale_wording.locale => locale_hash }
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def inner_keys(label:)
|
15
|
+
label.split('.')
|
16
|
+
end
|
17
|
+
|
18
|
+
def map_singulars(simple_wordings:)
|
19
|
+
map_translations(translations: simple_wordings) do |inner_keys, translation|
|
20
|
+
dotted_key_to_hash(inner_keys, { inner_keys.pop => translation.value })
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def map_plurals(coumpound_wordings:)
|
25
|
+
result = {}
|
26
|
+
coumpound_wordings.each do |label, simple_wordings|
|
27
|
+
variants_hash = map_translations(translations: simple_wordings.values) do |keys, translation|
|
28
|
+
dotted_key_to_hash(keys, { translation.key.variant_name => translation.value })
|
27
29
|
end
|
30
|
+
result.deep_merge!(variants_hash)
|
31
|
+
end
|
32
|
+
result
|
33
|
+
end
|
34
|
+
|
35
|
+
def map_translations(translations:)
|
36
|
+
translations.each_with_object({}) do |translation, hash|
|
37
|
+
keys = inner_keys(label: translation.key.label)
|
38
|
+
inner_keys_hash = yield(keys, translation)
|
39
|
+
hash.deep_merge!(inner_keys_hash)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def dotted_key_to_hash(array, h)
|
44
|
+
if array.size.zero?
|
45
|
+
h
|
46
|
+
elsif array.size == 1
|
47
|
+
{ array.first => h }
|
48
|
+
elsif array.size > 1
|
49
|
+
{ array.first => dotted_key_to_hash(array[1..-1], h) }
|
28
50
|
end
|
29
|
-
{ locale_wording.locale => result }
|
30
51
|
end
|
31
52
|
end
|
32
53
|
end
|
33
|
-
end
|
54
|
+
end
|
@@ -1,28 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module AdLocalize
|
2
3
|
module Mappers
|
3
4
|
class OptionsToExportRequest
|
4
5
|
def map(options:)
|
5
|
-
Requests::ExportRequest.new
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
def map_g_spreadsheet_options(options:)
|
18
|
-
return unless options[:'drive-key']
|
19
|
-
Requests::GSpreadsheetOptions.new(
|
20
|
-
spreadsheet_id: options[:'drive-key'],
|
21
|
-
sheet_ids: options[:'sheets'],
|
22
|
-
export_all: options[:'export-all-sheets'],
|
23
|
-
service_account_config: ENV['GCLOUD_CLIENT_SECRET']
|
24
|
-
)
|
6
|
+
request = Requests::ExportRequest.new
|
7
|
+
request.locales = options[:locales]
|
8
|
+
request.bypass_empty_values = options[:'non-empty-values']
|
9
|
+
request.csv_paths = options[:csv_paths]
|
10
|
+
request.merge_policy = options[:'merge-policy']
|
11
|
+
request.output_path = options[:'target-dir']
|
12
|
+
request.platforms = options[:only]
|
13
|
+
request.spreadsheet_id = options[:'drive-key']
|
14
|
+
request.sheet_ids = options[:sheets]
|
15
|
+
request.export_all = options[:'export-all-sheets']
|
16
|
+
request.verbose = options[:debug]
|
17
|
+
request
|
25
18
|
end
|
26
19
|
end
|
27
20
|
end
|
28
|
-
end
|
21
|
+
end
|
@@ -1,38 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module AdLocalize
|
2
3
|
class OptionHandler
|
4
|
+
DEFAULT_OPTIONS = {
|
5
|
+
locales: Requests::ExportRequest::DEFAULTS[:locales],
|
6
|
+
:'non-empty-values' => Requests::ExportRequest::DEFAULTS[:bypass_empty_values],
|
7
|
+
csv_paths: Requests::ExportRequest::DEFAULTS[:csv_paths],
|
8
|
+
:'merge-policy' => Requests::ExportRequest::DEFAULTS[:merge_policy],
|
9
|
+
:'target-dir' => Requests::ExportRequest::DEFAULTS[:output_path],
|
10
|
+
:'drive-key' => Requests::ExportRequest::DEFAULTS[:spreadsheet_id],
|
11
|
+
sheets: Requests::ExportRequest::DEFAULTS[:sheet_ids],
|
12
|
+
:'export-all-sheets' => Requests::ExportRequest::DEFAULTS[:export_all],
|
13
|
+
debug: Requests::ExportRequest::DEFAULTS[:verbose],
|
14
|
+
only: Requests::ExportRequest::DEFAULTS[:platforms]
|
15
|
+
}
|
16
|
+
|
3
17
|
def self.parse!(options)
|
4
|
-
|
5
|
-
|
18
|
+
args = DEFAULT_OPTIONS
|
19
|
+
export_all_option = <<~DOC
|
20
|
+
Export all sheets from spreadsheet specified by --drive-key option.
|
21
|
+
\tBy default, generates one export directory per sheet (see -m|--merge-sheets option to merge them).
|
22
|
+
\tAn GCLOUD_CLIENT_SECRET environment variable containing the client_secret.json content is needed.
|
23
|
+
DOC
|
24
|
+
merge_policy_option = <<~DOC
|
25
|
+
Merge specified csv (or sheets from --export-all) instead of exporting each csv.
|
26
|
+
\treplace: if a key is already defined, replace its value.
|
27
|
+
\tkeep: if a key is already defined, keep the previous value.
|
28
|
+
DOC
|
29
|
+
platforms_option = <<~DOC
|
30
|
+
PLATFORMS is a comma separated list.
|
31
|
+
\tOnly generate localisation files for the specified platforms.
|
32
|
+
\tSupported platforms : #{Entities::Platform::SUPPORTED_PLATFORMS.to_sentence}
|
33
|
+
DOC
|
6
34
|
|
7
|
-
|
8
|
-
parser.
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
\tAn GCLOUD_CLIENT_SECRET environment variable containing the client_secret.json content is needed.
|
13
|
-
DOC
|
14
|
-
)
|
15
|
-
parser.on("-h", "--help", "Prints help") do
|
35
|
+
OptionParser.new do |parser|
|
36
|
+
parser.banner = 'Usage: exe/ad_localize [options] file(s)'
|
37
|
+
parser.on("-d", "--debug", TrueClass, 'Run in debug mode')
|
38
|
+
parser.on("-e", "--export-all-sheets", TrueClass, export_all_option)
|
39
|
+
parser.on("-h", "--help", 'Prints help') do
|
16
40
|
puts parser
|
17
41
|
exit
|
18
42
|
end
|
19
|
-
parser.on("-k", "--drive-key SPREADSHEET_ID", String,
|
20
|
-
parser.on("-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
)
|
27
|
-
parser.on("-
|
28
|
-
|
29
|
-
|
30
|
-
|
43
|
+
parser.on("-k", "--drive-key SPREADSHEET_ID", String, 'Use google drive spreadsheets')
|
44
|
+
parser.on("-l", "--locales LOCALES", Array,
|
45
|
+
'LOCALES is a comma separated list. Only generate localisation files for the specified locales')
|
46
|
+
parser.on("-m", "--merge-policy POLICY", Interactors::MergeWordings::MERGE_POLICIES, merge_policy_option)
|
47
|
+
parser.on("-o", "--only PLATFORMS", Array, platforms_option)
|
48
|
+
parser.on("-s", "--sheets SHEET_IDS", Array,
|
49
|
+
'SHEET_IDS is a comma separated list. Use a specific sheet id for Google Drive spreadsheets with several sheets')
|
50
|
+
parser.on("-t", "--target-dir PATH", String, 'Path to the target directory')
|
51
|
+
parser.on("-v", "--version", 'Prints current version') do
|
52
|
+
puts AdLocalize::VERSION
|
53
|
+
exit
|
54
|
+
end
|
55
|
+
parser.on("-x", "--non-empty-values", TrueClass, 'Do not export keys with empty values (iOS only)')
|
56
|
+
end.parse!(options, into: args)
|
31
57
|
|
32
|
-
args = {}
|
33
|
-
option_parser.parse!(options, into: args)
|
34
58
|
args[:csv_paths] = options
|
35
59
|
return args
|
36
60
|
end
|
37
61
|
end
|
38
|
-
end
|
62
|
+
end
|