ad_localize 5.0.0 → 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 +24 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +54 -48
- data/README.md +32 -10
- data/Rakefile +1 -0
- data/ad_localize.gemspec +10 -9
- data/bin/console +1 -0
- 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 +26 -20
- 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 -22
- data/lib/ad_localize/option_handler.rb +50 -27
- 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 +95 -57
- 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 -15
- data/lib/ad_localize/serializers/localizable_stringsdict_serializer.rb +12 -25
- 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 -35
- metadata +70 -47
- 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 -45
- data/lib/ad_localize/interactors/export_csv_files.rb +0 -20
- data/lib/ad_localize/interactors/export_g_spreadsheet.rb +0 -64
- data/lib/ad_localize/interactors/platforms/export_android_locale_wording.rb +0 -44
- data/lib/ad_localize/interactors/platforms/export_csv_locale_wording.rb +0 -22
- data/lib/ad_localize/interactors/platforms/export_ios_locale_wording.rb +0 -75
- 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 -32
- 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/export_wording_options.rb +0 -24
- 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
@@ -1,75 +0,0 @@
|
|
1
|
-
module AdLocalize
|
2
|
-
module Interactors
|
3
|
-
module Platforms
|
4
|
-
class ExportIOSLocaleWording
|
5
|
-
INFO_PLIST_FILENAME = "InfoPlist.strings".freeze
|
6
|
-
LOCALIZABLE_STRINGS_FILENAME = "Localizable.strings".freeze
|
7
|
-
LOCALIZABLE_STRINGSDICT_FILENAME = "Localizable.stringsdict".freeze
|
8
|
-
LOCALE_DIRECTORY_CONVENTION = "%{locale}.lproj".freeze
|
9
|
-
|
10
|
-
def initialize
|
11
|
-
@info_plist_serializer = Serializers::InfoPlistSerializer.new
|
12
|
-
@strings_serializer = Serializers::LocalizableStringsSerializer.new
|
13
|
-
@stringsdict_serializer = Serializers::LocalizableStringsdictSerializer.new
|
14
|
-
@file_system_repository = Repositories::FileSystemRepository.new
|
15
|
-
end
|
16
|
-
|
17
|
-
def call(export_wording_options:)
|
18
|
-
bypass_empty_values = export_wording_options.bypass_empty_values
|
19
|
-
|
20
|
-
export_wording_options.locales.each do |locale|
|
21
|
-
LOGGER.debug("Starting export iOS wording for locale #{locale}")
|
22
|
-
locale_wording = export_wording_options.wording.translations_for(locale: locale)
|
23
|
-
next unless has_ios_wording?(locale_wording: locale_wording)
|
24
|
-
|
25
|
-
locale_directory_name = LOCALE_DIRECTORY_CONVENTION % { locale: locale }
|
26
|
-
output_dir = export_wording_options.platform_output_directory.join(locale_directory_name)
|
27
|
-
@file_system_repository.create_directory(path: output_dir)
|
28
|
-
export_files(locale_wording: locale_wording, output_dir: output_dir, bypass_empty_values: bypass_empty_values)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def export_files(locale_wording:, output_dir:, bypass_empty_values:)
|
35
|
-
export_info_plist(locale_wording: locale_wording, output_dir: output_dir)
|
36
|
-
export_localizable_strings(locale_wording: locale_wording, output_dir: output_dir, bypass_empty_values: bypass_empty_values)
|
37
|
-
export_localizable_stringsdict(locale_wording: locale_wording, output_dir: output_dir, bypass_empty_values: bypass_empty_values)
|
38
|
-
end
|
39
|
-
|
40
|
-
def has_ios_wording?(locale_wording:)
|
41
|
-
locale_wording.has_info_plist_keys? ||
|
42
|
-
locale_wording.has_singular_keys? ||
|
43
|
-
locale_wording.has_plural_keys? ||
|
44
|
-
locale_wording.has_adaptive_keys?
|
45
|
-
end
|
46
|
-
|
47
|
-
def export_info_plist(locale_wording:, output_dir:)
|
48
|
-
return unless locale_wording.has_info_plist_keys?
|
49
|
-
|
50
|
-
content = @info_plist_serializer.render(locale_wording: locale_wording)
|
51
|
-
@file_system_repository.write(content: content, path: output_dir.join(INFO_PLIST_FILENAME))
|
52
|
-
LOGGER.debug("#{INFO_PLIST_FILENAME} done !")
|
53
|
-
end
|
54
|
-
|
55
|
-
def export_localizable_strings(locale_wording:, output_dir:, bypass_empty_values:)
|
56
|
-
return unless locale_wording.has_singular_keys?
|
57
|
-
|
58
|
-
@strings_serializer.bypass_empty_values = bypass_empty_values
|
59
|
-
content = @strings_serializer.render(locale_wording: locale_wording)
|
60
|
-
@file_system_repository.write(content: content, path: output_dir.join(LOCALIZABLE_STRINGS_FILENAME))
|
61
|
-
LOGGER.debug("#{LOCALIZABLE_STRINGS_FILENAME} done !")
|
62
|
-
end
|
63
|
-
|
64
|
-
def export_localizable_stringsdict(locale_wording:, output_dir:, bypass_empty_values:)
|
65
|
-
return unless locale_wording.has_plural_keys? || locale_wording.has_adaptive_keys?
|
66
|
-
|
67
|
-
@stringsdict_serializer.bypass_empty_values = bypass_empty_values
|
68
|
-
content = @stringsdict_serializer.render(locale_wording: locale_wording)
|
69
|
-
@file_system_repository.write(content: content, path: output_dir.join(LOCALIZABLE_STRINGSDICT_FILENAME))
|
70
|
-
LOGGER.debug("#{LOCALIZABLE_STRINGSDICT_FILENAME} done !")
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
module AdLocalize
|
2
|
-
module Interactors
|
3
|
-
module Platforms
|
4
|
-
class ExportJSONLocaleWording
|
5
|
-
def initialize
|
6
|
-
@json_serializer = Serializers::JSONSerializer.new
|
7
|
-
@file_system_repository = Repositories::FileSystemRepository.new
|
8
|
-
end
|
9
|
-
|
10
|
-
def call(export_wording_options:)
|
11
|
-
output_dir = export_wording_options.platform_output_directory
|
12
|
-
|
13
|
-
export_wording_options.locales.each do |locale|
|
14
|
-
LOGGER.debug("Starting export JSON wording for locale #{locale}")
|
15
|
-
locale_wording = export_wording_options.wording.translations_for(locale: locale)
|
16
|
-
content = @json_serializer.render(locale_wording: locale_wording)
|
17
|
-
next if content[locale].blank?
|
18
|
-
|
19
|
-
@file_system_repository.create_directory(path: output_dir)
|
20
|
-
@file_system_repository.write(content: content, path: output_dir.join("#{locale}.json"))
|
21
|
-
LOGGER.debug("#{locale}.json done !")
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
module AdLocalize
|
2
|
-
module Interactors
|
3
|
-
module Platforms
|
4
|
-
class ExportPlatformFactory
|
5
|
-
def build(platform:)
|
6
|
-
case platform
|
7
|
-
when 'json'
|
8
|
-
json_builder
|
9
|
-
when 'yml'
|
10
|
-
yaml_builder
|
11
|
-
when 'android'
|
12
|
-
android_builder
|
13
|
-
when 'ios'
|
14
|
-
ios_builder
|
15
|
-
when 'properties'
|
16
|
-
properties_builder
|
17
|
-
when 'csv'
|
18
|
-
csv_builder
|
19
|
-
else
|
20
|
-
raise ArgumentError.new('Unknown platform for builder factory')
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def json_builder
|
25
|
-
@json_builder ||= ExportJSONLocaleWording.new
|
26
|
-
end
|
27
|
-
|
28
|
-
def yaml_builder
|
29
|
-
@yaml_builder ||= ExportYAMLLocaleWording.new
|
30
|
-
end
|
31
|
-
|
32
|
-
def android_builder
|
33
|
-
@android_builder ||= ExportAndroidLocaleWording.new
|
34
|
-
end
|
35
|
-
|
36
|
-
def ios_builder
|
37
|
-
@ios_builder ||= ExportIOSLocaleWording.new
|
38
|
-
end
|
39
|
-
|
40
|
-
def properties_builder
|
41
|
-
@properties_builder ||= ExportPropertiesLocaleWording.new
|
42
|
-
end
|
43
|
-
|
44
|
-
def csv_builder
|
45
|
-
@csv_builder ||= ExportCSVLocaleWording.new
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
module AdLocalize
|
2
|
-
module Interactors
|
3
|
-
module Platforms
|
4
|
-
class ExportPropertiesLocaleWording
|
5
|
-
def initialize
|
6
|
-
@properties_serializer = Serializers::PropertiesSerializer.new
|
7
|
-
@file_system_repository = Repositories::FileSystemRepository.new
|
8
|
-
end
|
9
|
-
|
10
|
-
def call(export_wording_options:)
|
11
|
-
export_wording_options.locales.each do |locale|
|
12
|
-
LOGGER.debug("Starting export Properties wording for locale #{locale}")
|
13
|
-
locale_wording = export_wording_options.wording.translations_for(locale: locale)
|
14
|
-
return unless has_properties_wording?(locale_wording: locale_wording)
|
15
|
-
|
16
|
-
content = @properties_serializer.render(locale_wording: locale_wording)
|
17
|
-
@file_system_repository.create_directory(path: export_wording_options.platform_output_directory)
|
18
|
-
output_path = export_wording_options.platform_output_directory.join("#{locale}.properties")
|
19
|
-
@file_system_repository.write(content: content, path: output_path)
|
20
|
-
LOGGER.debug("#{locale}.properties done !")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def has_properties_wording?(locale_wording:)
|
27
|
-
locale_wording.has_singular_keys?
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
module AdLocalize
|
2
|
-
module Interactors
|
3
|
-
module Platforms
|
4
|
-
class ExportYAMLLocaleWording
|
5
|
-
def initialize
|
6
|
-
@yaml_serializer = Serializers::YAMLSerializer.new
|
7
|
-
@file_system_repository = Repositories::FileSystemRepository.new
|
8
|
-
end
|
9
|
-
|
10
|
-
def call(export_wording_options:)
|
11
|
-
output_dir = export_wording_options.platform_output_directory
|
12
|
-
|
13
|
-
export_wording_options.locales.each do |locale|
|
14
|
-
LOGGER.debug("Starting export YAML wording for locale #{locale}")
|
15
|
-
locale_wording = export_wording_options.wording.translations_for(locale: locale)
|
16
|
-
content = @yaml_serializer.render(locale_wording: locale_wording)
|
17
|
-
next if content[locale].blank?
|
18
|
-
|
19
|
-
@file_system_repository.create_directory(path: output_dir)
|
20
|
-
@file_system_repository.write(content: content, path: output_dir.join("#{locale}.yml"))
|
21
|
-
LOGGER.debug("#{locale}.yml done !")
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,73 +0,0 @@
|
|
1
|
-
module AdLocalize
|
2
|
-
module Mappers
|
3
|
-
class CSVPathToWording
|
4
|
-
def map(csv_path:)
|
5
|
-
@headers = CSV.foreach(csv_path).first
|
6
|
-
return unless valid?(csv_path: csv_path)
|
7
|
-
translations = []
|
8
|
-
validator = Validators::KeyValidator.new
|
9
|
-
|
10
|
-
CSV.foreach(csv_path, headers: true, skip_blanks: true) do |row|
|
11
|
-
row_translations = map_row(row: row, locales: locales)
|
12
|
-
next if row_translations.blank?
|
13
|
-
|
14
|
-
current_key = row_translations.first.key
|
15
|
-
next if validator.has_warnings?(current_key)
|
16
|
-
|
17
|
-
translations.concat(row_translations)
|
18
|
-
end
|
19
|
-
|
20
|
-
locale_wordings = translations.group_by(&:locale).map do |locale, group|
|
21
|
-
Entities::LocaleWording.new(locale: locale, translations: group)
|
22
|
-
end
|
23
|
-
Entities::Wording.new(locale_wordings: locale_wordings, default_locale: locales.first)
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def valid?(csv_path:)
|
29
|
-
File.exist?(csv_path) && has_key_column? && has_locales?
|
30
|
-
end
|
31
|
-
|
32
|
-
def locales
|
33
|
-
@locales ||= compute_locales
|
34
|
-
end
|
35
|
-
|
36
|
-
def compute_locales
|
37
|
-
return [] unless has_key_column? && key_column_index < @headers.size.pred
|
38
|
-
|
39
|
-
@headers.slice(key_column_index.succ..-1).compact.reject do |header|
|
40
|
-
header.to_s.include?(Constant::COMMENT_KEY_COLUMN_IDENTIFIER)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def has_locales?
|
45
|
-
locales.present?
|
46
|
-
end
|
47
|
-
|
48
|
-
def has_key_column?
|
49
|
-
key_column_index.present?
|
50
|
-
end
|
51
|
-
|
52
|
-
def key_column_index
|
53
|
-
@key_column_index ||= @headers.index(Constant::CSV_WORDING_KEYS_COLUMN)
|
54
|
-
end
|
55
|
-
|
56
|
-
def map_row(row:, locales:)
|
57
|
-
csv_wording_key = row.field(Constant::CSV_WORDING_KEYS_COLUMN)
|
58
|
-
return if csv_wording_key.blank?
|
59
|
-
|
60
|
-
key = Entities::Key.new(label: csv_wording_key)
|
61
|
-
locales.map do |locale|
|
62
|
-
comment_column_name = "#{Constant::COMMENT_KEY_COLUMN_IDENTIFIER} #{locale}"
|
63
|
-
Entities::Translation.new(
|
64
|
-
locale: locale,
|
65
|
-
key: key,
|
66
|
-
value: row.field(locale),
|
67
|
-
comment: row.field(comment_column_name)
|
68
|
-
)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
module AdLocalize
|
2
|
-
module Mappers
|
3
|
-
class TranslationGroupMapper
|
4
|
-
def initialize(translation_mapper: TranslationMapper.new)
|
5
|
-
@translation_mapper = translation_mapper
|
6
|
-
end
|
7
|
-
|
8
|
-
def map(label:, translations:)
|
9
|
-
translation_view_models = translations.map { |translation| @translation_mapper.map(translation: translation) }
|
10
|
-
ViewModels::TranslationGroupViewModel.new(label: label, translation_view_models: translation_view_models)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
module AdLocalize
|
2
|
-
module Mappers
|
3
|
-
class TranslationMapper
|
4
|
-
def map(translation:)
|
5
|
-
ViewModels::TranslationViewModel.new(
|
6
|
-
label: translation.key.label,
|
7
|
-
key: key(translation: translation),
|
8
|
-
value: sanitize_value(value: translation.value),
|
9
|
-
comment: translation.comment
|
10
|
-
)
|
11
|
-
end
|
12
|
-
|
13
|
-
protected
|
14
|
-
|
15
|
-
def sanitize_value(value:)
|
16
|
-
value
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def key(translation:)
|
22
|
-
if translation.key.plural?
|
23
|
-
translation.key.plural_key
|
24
|
-
elsif translation.key.adaptive?
|
25
|
-
translation.key.adaptive_key
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
@@ -1,67 +0,0 @@
|
|
1
|
-
module AdLocalize
|
2
|
-
module Mappers
|
3
|
-
class ValueRangeToWording
|
4
|
-
def map(value_range:)
|
5
|
-
values = value_range.values
|
6
|
-
analyze_header(first_row: values.first)
|
7
|
-
return unless valid_header?
|
8
|
-
|
9
|
-
translations = map_rows(values: values)
|
10
|
-
locale_wordings = translations.group_by(&:locale).map do |locale, group|
|
11
|
-
Entities::LocaleWording.new(locale: locale, translations: group)
|
12
|
-
end
|
13
|
-
Entities::Wording.new(locale_wordings: locale_wordings, default_locale: @locale_mapping.keys.first)
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def map_rows(values:)
|
19
|
-
translations = []
|
20
|
-
validator = Validators::KeyValidator.new
|
21
|
-
|
22
|
-
values[1..-1].each do |row|
|
23
|
-
row_translations = map_row(row: row)
|
24
|
-
next if row_translations.blank?
|
25
|
-
|
26
|
-
current_key = row_translations.first.key
|
27
|
-
next if validator.has_warnings?(current_key)
|
28
|
-
|
29
|
-
translations.concat(row_translations)
|
30
|
-
end
|
31
|
-
translations
|
32
|
-
end
|
33
|
-
|
34
|
-
def analyze_header(first_row:)
|
35
|
-
@header = first_row
|
36
|
-
@key_index = first_row.index(Constant::CSV_WORDING_KEYS_COLUMN)
|
37
|
-
@locale_mapping = {}
|
38
|
-
first_row[@key_index.succ..-1].each_index do |relative_index|
|
39
|
-
absolute_index = @key_index.succ + relative_index
|
40
|
-
next if first_row[absolute_index].blank? || first_row[absolute_index].include?(Constant::COMMENT_KEY_COLUMN_IDENTIFIER)
|
41
|
-
@locale_mapping[first_row[absolute_index]] = { key_index: absolute_index }
|
42
|
-
comment_column_name = "#{Constant::COMMENT_KEY_COLUMN_IDENTIFIER} #{first_row[absolute_index]}"
|
43
|
-
@locale_mapping[first_row[absolute_index]][:comment_index] = first_row.index(comment_column_name)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def map_row(row:)
|
48
|
-
csv_wording_key = row[@key_index]
|
49
|
-
return if csv_wording_key.blank?
|
50
|
-
key = Entities::Key.new(label: csv_wording_key)
|
51
|
-
@locale_mapping.map do |locale, index_mapping|
|
52
|
-
comment = index_mapping[:comment_index].nil? ? nil : row[index_mapping[:comment_index]]
|
53
|
-
Entities::Translation.new(
|
54
|
-
locale: locale,
|
55
|
-
key: key,
|
56
|
-
value: row[index_mapping[:key_index]],
|
57
|
-
comment: comment
|
58
|
-
)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def valid_header?
|
63
|
-
@key_index.present? || @locale_mapping.keys.size.positive?
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
module AdLocalize
|
2
|
-
module Repositories
|
3
|
-
class GSheetsRepository
|
4
|
-
SCOPES = [Google::Apis::SheetsV4::AUTH_SPREADSHEETS_READONLY]
|
5
|
-
ROWS_MAJOR_DIMENSION = 'ROWS'.freeze
|
6
|
-
SPREADSHEET_APPLICATION_NAME = 'ad_localize'.freeze
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
@service = Google::Apis::SheetsV4::SheetsService.new
|
10
|
-
@service.client_options.application_name = SPREADSHEET_APPLICATION_NAME
|
11
|
-
end
|
12
|
-
|
13
|
-
def get_sheets_values(g_spreadsheet_options:)
|
14
|
-
configure(json_configuration: g_spreadsheet_options.service_account_config) if @service.authorization.nil?
|
15
|
-
spreadsheet = @service.get_spreadsheet(g_spreadsheet_options.spreadsheet_id)
|
16
|
-
if g_spreadsheet_options.export_all
|
17
|
-
spreadsheet.sheets.map { |sheet| get_sheet_values(spreadsheet_id: g_spreadsheet_options.spreadsheet_id, sheet: sheet) }
|
18
|
-
elsif g_spreadsheet_options.sheet_ids.nil? || g_spreadsheet_options.sheet_ids.size.zero?
|
19
|
-
spreadsheet.sheets[0..0].map { |sheet| get_sheet_values(spreadsheet_id: g_spreadsheet_options.spreadsheet_id, sheet: sheet) }
|
20
|
-
else
|
21
|
-
spreadsheet.sheets.select do |sheet|
|
22
|
-
g_spreadsheet_options.sheet_ids.include?(sheet.properties.sheet_id.to_s)
|
23
|
-
end.map do |sheet|
|
24
|
-
get_sheet_values(spreadsheet_id: g_spreadsheet_options.spreadsheet_id, sheet: sheet)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def configure(json_configuration:)
|
32
|
-
raise ArgumentError.new('No service account configuration') if json_configuration.blank?
|
33
|
-
json_key_io = StringIO.new(json_configuration)
|
34
|
-
authorizer = Google::Auth::ServiceAccountCredentials.make_creds(json_key_io: json_key_io, scope: SCOPES)
|
35
|
-
@service.authorization = authorizer
|
36
|
-
end
|
37
|
-
|
38
|
-
def get_sheet_values(spreadsheet_id:, sheet:)
|
39
|
-
range = sheet.properties.title
|
40
|
-
@service.get_spreadsheet_values(spreadsheet_id, range, major_dimension: ROWS_MAJOR_DIMENSION)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,24 +0,0 @@
|
|
1
|
-
module AdLocalize
|
2
|
-
module Requests
|
3
|
-
class ExportWordingOptions
|
4
|
-
def initialize(wording:, platform_output_directory:, locales: [], bypass_empty_values: false, csv_paths: [])
|
5
|
-
@wording = wording
|
6
|
-
@locales = locales
|
7
|
-
@platform_output_directory = platform_output_directory
|
8
|
-
@bypass_empty_values = bypass_empty_values
|
9
|
-
@csv_paths = csv_paths
|
10
|
-
end
|
11
|
-
|
12
|
-
attr_reader(
|
13
|
-
:wording,
|
14
|
-
:platform_output_directory,
|
15
|
-
:bypass_empty_values,
|
16
|
-
:locales
|
17
|
-
)
|
18
|
-
|
19
|
-
attr_accessor(
|
20
|
-
:csv_paths
|
21
|
-
)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
@@ -1,47 +0,0 @@
|
|
1
|
-
module AdLocalize
|
2
|
-
module Requests
|
3
|
-
class GSpreadsheetOptions
|
4
|
-
attr_accessor(
|
5
|
-
:spreadsheet_id,
|
6
|
-
:sheet_ids,
|
7
|
-
:export_all,
|
8
|
-
:service_account_config
|
9
|
-
)
|
10
|
-
|
11
|
-
def initialize(**args)
|
12
|
-
@spreadsheet_id = args[:spreadsheet_id]
|
13
|
-
@sheet_ids = Array(args[:sheet_ids])
|
14
|
-
@export_all = args[:export_all] || false
|
15
|
-
@service_account_config = args[:service_account_config].presence
|
16
|
-
end
|
17
|
-
|
18
|
-
def valid?
|
19
|
-
(spreadsheet_id && !export_all) || (spreadsheet_id && service_account_config.present?)
|
20
|
-
end
|
21
|
-
|
22
|
-
def public_download_urls
|
23
|
-
return [] if @service_account_config
|
24
|
-
if @sheet_ids.size.zero?
|
25
|
-
[public_download_url(sheet_id: nil)]
|
26
|
-
else
|
27
|
-
@sheet_ids.map { |sheet_id| public_download_url(sheet_id: sheet_id) }
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def has_multiple_sheets?
|
32
|
-
export_all || @sheet_ids.size > 1
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def public_download_url(sheet_id:)
|
38
|
-
query_id = sheet_id.blank? ? "id=#{@spreadsheet_id}" : "gid=#{sheet_id}"
|
39
|
-
"https://docs.google.com/spreadsheets/d/#{@spreadsheet_id}/export?format=csv&#{query_id}"
|
40
|
-
end
|
41
|
-
|
42
|
-
def valid_export_all_config
|
43
|
-
export_all && service_account_config.present?
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
module AdLocalize
|
2
|
-
module Requests
|
3
|
-
class MergePolicy
|
4
|
-
REPLACE_POLICY = 'replace'.freeze
|
5
|
-
KEEP_POLICY = 'keep'.freeze
|
6
|
-
MERGE_POLICIES = [KEEP_POLICY, REPLACE_POLICY]
|
7
|
-
DEFAULT_POLICY = KEEP_POLICY
|
8
|
-
|
9
|
-
attr_reader(:policy)
|
10
|
-
|
11
|
-
def initialize(policy:)
|
12
|
-
@policy = policy
|
13
|
-
end
|
14
|
-
|
15
|
-
def keep?
|
16
|
-
@policy == KEEP_POLICY
|
17
|
-
end
|
18
|
-
|
19
|
-
def replace?
|
20
|
-
@policy == REPLACE_POLICY
|
21
|
-
end
|
22
|
-
|
23
|
-
def valid?
|
24
|
-
@policy.present? && MERGE_POLICIES.include?(@policy)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module AdLocalize
|
2
|
-
module Serializers
|
3
|
-
module WithTemplate
|
4
|
-
TEMPLATES_DIRECTORY = __dir__ + "/../templates"
|
5
|
-
|
6
|
-
def render(locale_wording:)
|
7
|
-
hash_binding = hash_binding(locale_wording: locale_wording)
|
8
|
-
return unless hash_binding
|
9
|
-
render_template(template_path: template_path, hash_binding: hash_binding)
|
10
|
-
end
|
11
|
-
|
12
|
-
def render_template(template_path:, hash_binding:)
|
13
|
-
template = File.read(template_path)
|
14
|
-
renderer = ERB.new(template, trim_mode: '-')
|
15
|
-
renderer.result_with_hash(hash_binding)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
module AdLocalize
|
2
|
-
module Validators
|
3
|
-
class KeyValidator
|
4
|
-
|
5
|
-
def initialize
|
6
|
-
@existing_key_for_label = {}
|
7
|
-
end
|
8
|
-
|
9
|
-
def has_warnings?(current_key)
|
10
|
-
current_label = current_key.label
|
11
|
-
existing_key = @existing_key_for_label[current_label]
|
12
|
-
|
13
|
-
has_warnings = false
|
14
|
-
|
15
|
-
unless existing_key.nil?
|
16
|
-
existing_plural_key = existing_key.label == current_key.label && existing_key.plural? && current_key.singular?
|
17
|
-
existing_singular_key = existing_key.label == current_key.label && existing_key.singular? && current_key.plural?
|
18
|
-
is_same_key = existing_key.same_as?(key: current_key)
|
19
|
-
LOGGER.warn "A plural value already exist for key '#{current_label}'. Remove duplicates." if existing_plural_key
|
20
|
-
LOGGER.warn "A singular value already exist for key '#{current_label}'. Remove duplicates." if existing_singular_key
|
21
|
-
LOGGER.warn "Some values already exist for key '#{current_label}'. Remove duplicates." if is_same_key
|
22
|
-
has_warnings = is_same_key || existing_plural_key || existing_singular_key
|
23
|
-
end
|
24
|
-
|
25
|
-
@existing_key_for_label[current_label] = current_key
|
26
|
-
|
27
|
-
has_warnings
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module AdLocalize
|
2
|
-
module ViewModels
|
3
|
-
class TranslationGroupViewModel
|
4
|
-
attr_reader(
|
5
|
-
:label,
|
6
|
-
:translation_view_models
|
7
|
-
)
|
8
|
-
|
9
|
-
def initialize(label:, translation_view_models:)
|
10
|
-
@label = label
|
11
|
-
@translation_view_models = translation_view_models
|
12
|
-
end
|
13
|
-
|
14
|
-
def has_translations?
|
15
|
-
(translation_view_models || []).any?(&:has_value?)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
module AdLocalize
|
2
|
-
module ViewModels
|
3
|
-
class TranslationViewModel
|
4
|
-
attr_reader(
|
5
|
-
:label,
|
6
|
-
:key,
|
7
|
-
:value,
|
8
|
-
:comment
|
9
|
-
)
|
10
|
-
|
11
|
-
def initialize(label:, key:, value:, comment:)
|
12
|
-
@label = label
|
13
|
-
@key = key
|
14
|
-
@value = value
|
15
|
-
@comment = comment
|
16
|
-
end
|
17
|
-
|
18
|
-
def has_value?
|
19
|
-
value.present?
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|