ad_localize 3.6.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +41 -1
- data/Gemfile.lock +34 -11
- data/README.md +148 -145
- data/ad_localize.gemspec +2 -0
- data/bin/console +1 -0
- data/exe/ad_localize +1 -1
- data/lib/ad_localize.rb +52 -11
- data/lib/ad_localize/ad_logger.rb +22 -9
- data/lib/ad_localize/cli.rb +10 -0
- data/lib/ad_localize/constant.rb +2 -21
- data/lib/ad_localize/entities/key.rb +74 -0
- data/lib/ad_localize/entities/locale_wording.rb +60 -0
- data/lib/ad_localize/entities/translation.rb +20 -0
- data/lib/ad_localize/entities/wording.rb +24 -0
- data/lib/ad_localize/interactors/execute_export_request.rb +43 -0
- data/lib/ad_localize/interactors/export_csv_files.rb +17 -0
- data/lib/ad_localize/interactors/export_g_spreadsheet.rb +55 -0
- data/lib/ad_localize/interactors/export_wording.rb +27 -0
- data/lib/ad_localize/interactors/merge_wordings.rb +43 -0
- data/lib/ad_localize/interactors/platforms/export_android_locale_wording.rb +39 -0
- data/lib/ad_localize/interactors/platforms/export_ios_locale_wording.rb +62 -0
- data/lib/ad_localize/interactors/platforms/export_json_locale_wording.rb +23 -0
- data/lib/ad_localize/interactors/platforms/export_platform_factory.rb +44 -0
- data/lib/ad_localize/interactors/platforms/export_properties_locale_wording.rb +29 -0
- data/lib/ad_localize/interactors/platforms/export_yaml_locale_wording.rb +23 -0
- data/lib/ad_localize/mappers/android_translation_mapper.rb +18 -0
- data/lib/ad_localize/mappers/csv_path_to_wording.rb +76 -0
- data/lib/ad_localize/mappers/ios_translation_mapper.rb +12 -0
- data/lib/ad_localize/mappers/locale_wording_to_hash.rb +25 -0
- data/lib/ad_localize/mappers/options_to_export_request.rb +28 -0
- data/lib/ad_localize/mappers/translation_group_mapper.rb +14 -0
- data/lib/ad_localize/mappers/translation_mapper.rb +30 -0
- data/lib/ad_localize/mappers/value_range_to_wording.rb +69 -0
- data/lib/ad_localize/option_handler.rb +30 -57
- data/lib/ad_localize/repositories/file_system_repository.rb +13 -0
- data/lib/ad_localize/repositories/g_sheets_repository.rb +44 -0
- data/lib/ad_localize/requests/export_request.rb +77 -0
- data/lib/ad_localize/requests/g_spreadsheet_options.rb +47 -0
- data/lib/ad_localize/requests/merge_policy.rb +28 -0
- data/lib/ad_localize/serializers/info_plist_serializer.rb +27 -0
- data/lib/ad_localize/serializers/json_serializer.rb +13 -0
- data/lib/ad_localize/serializers/localizable_strings_serializer.rb +27 -0
- data/lib/ad_localize/serializers/localizable_stringsdict_serializer.rb +35 -0
- data/lib/ad_localize/serializers/properties_serializer.rb +25 -0
- data/lib/ad_localize/serializers/strings_serializer.rb +33 -0
- data/lib/ad_localize/serializers/with_template.rb +19 -0
- data/lib/ad_localize/serializers/yaml_serializer.rb +13 -0
- data/lib/ad_localize/templates/android/strings.xml.erb +19 -0
- data/lib/ad_localize/templates/ios/InfoPlist.strings.erb +3 -0
- data/lib/ad_localize/templates/ios/Localizable.strings.erb +3 -0
- data/lib/ad_localize/templates/ios/Localizable.stringsdict.erb +41 -0
- data/lib/ad_localize/templates/properties/template.properties.erb +3 -0
- data/lib/ad_localize/version.rb +1 -1
- data/lib/ad_localize/view_models/translation_group_view_model.rb +15 -0
- data/lib/ad_localize/view_models/translation_view_model.rb +19 -0
- metadata +74 -11
- data/Makefile +0 -11
- data/lib/ad_localize/csv_file_manager.rb +0 -64
- data/lib/ad_localize/csv_parser.rb +0 -165
- data/lib/ad_localize/platform/android_formatter.rb +0 -70
- data/lib/ad_localize/platform/ios_formatter.rb +0 -143
- data/lib/ad_localize/platform/json_formatter.rb +0 -17
- data/lib/ad_localize/platform/platform_formatter.rb +0 -109
- data/lib/ad_localize/platform/yml_formatter.rb +0 -19
- data/lib/ad_localize/runner.rb +0 -55
@@ -1,165 +0,0 @@
|
|
1
|
-
module AdLocalize
|
2
|
-
class CsvParser
|
3
|
-
CSV_WORDING_KEYS_COLUMN = "key"
|
4
|
-
PLURAL_KEY_REGEXP = /\#\#\{([A-Za-z]+)\}/
|
5
|
-
ADAPTIVE_KEY_REGEXP = /\#\#\{(\d+)\}/
|
6
|
-
INFO_PLIST_KEY_REGEXP = /(NS.+UsageDescription)|(CF.+Name)/ # see https://developer.apple.com/documentation/bundleresources/information_property_list
|
7
|
-
|
8
|
-
attr_accessor :locales
|
9
|
-
|
10
|
-
def initialize
|
11
|
-
@locales = []
|
12
|
-
end
|
13
|
-
|
14
|
-
# Raise a StandardError if no locale is detected in the csv
|
15
|
-
def extract_data(file_name)
|
16
|
-
data = {}
|
17
|
-
CSV.foreach(file_name, headers: true, skip_blanks: true) do |row|
|
18
|
-
validity_status = check_row(row)
|
19
|
-
if validity_status.zero?
|
20
|
-
keys_column_index = row.index(CSV_WORDING_KEYS_COLUMN)
|
21
|
-
fields = row.fields
|
22
|
-
LOGGER.log(:warn, :yellow, "Missing key in line #{$.}") unless fields[keys_column_index...fields.count].all?(&:nil?)
|
23
|
-
next
|
24
|
-
elsif validity_status == -1
|
25
|
-
LOGGER.log(:error, :red, "[CSV FORMAT] #{file_name} is not a valid file")
|
26
|
-
exit
|
27
|
-
else
|
28
|
-
find_locales(row) if locales.empty?
|
29
|
-
row_data = parse_row(row)
|
30
|
-
data.deep_merge!(row_data) unless row_data.nil?
|
31
|
-
end
|
32
|
-
end
|
33
|
-
remove_numeral_conflicts!(data)
|
34
|
-
data
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
# Returns 1 if row is ok, 0 if row there are missing information and -1 if row is not a csv row
|
40
|
-
def check_row(row)
|
41
|
-
valid_row = 1
|
42
|
-
# Check non empty row
|
43
|
-
if row.field(CSV_WORDING_KEYS_COLUMN).nil?
|
44
|
-
valid_row = 0
|
45
|
-
elsif not row.headers.include?(CSV_WORDING_KEYS_COLUMN)
|
46
|
-
valid_row = -1
|
47
|
-
end
|
48
|
-
return valid_row
|
49
|
-
end
|
50
|
-
|
51
|
-
def find_locales(row)
|
52
|
-
wording_key_column_index = row.index(CSV_WORDING_KEYS_COLUMN)
|
53
|
-
if row.length > wording_key_column_index
|
54
|
-
self.locales = row.headers.slice((wording_key_column_index+1)..-1).compact.reject do |header|
|
55
|
-
header.to_s.include? Constant::COMMENT_KEY_COLUMN_IDENTIFIER
|
56
|
-
end
|
57
|
-
end
|
58
|
-
if locales.empty?
|
59
|
-
raise 'NO DETECTED LOCALES'
|
60
|
-
else
|
61
|
-
LOGGER.log(:debug, :green, "DETECTED LOCALES : #{locales.join(', ')}")
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def parse_row(row)
|
66
|
-
key_infos = parse_key(row)
|
67
|
-
return nil if key_infos.nil?
|
68
|
-
|
69
|
-
locales.each_with_object({ key_infos.dig(:key) => {} }) do |locale, output|
|
70
|
-
current_key = key_infos.dig(:key)
|
71
|
-
current_key_already_has_wording_for_locale = output[current_key].key? locale.to_sym
|
72
|
-
output[current_key][locale.to_sym] = { key_infos.dig(:numeral_key) => {} } unless current_key_already_has_wording_for_locale
|
73
|
-
|
74
|
-
if key_infos.dig(:numeral_key) == Constant::SINGULAR_KEY_SYMBOL
|
75
|
-
trace_wording(row[locale], "[#{locale.upcase}] Singular key ---> #{current_key}", "[#{locale.upcase}] Missing translation for #{current_key}")
|
76
|
-
value = row[locale] || default_wording(locale, current_key)
|
77
|
-
elsif key_infos.dig(:numeral_key) == Constant::PLURAL_KEY_SYMBOL
|
78
|
-
trace_wording(row[locale],
|
79
|
-
"[#{locale.upcase}] Plural key ---> plural_identifier : #{key_infos.dig(:plural_identifier)}, key : #{current_key}",
|
80
|
-
"[#{locale.upcase}] Missing translation for #{current_key} (#{key_infos.dig(:plural_identifier)})")
|
81
|
-
value = { key_infos.dig(:plural_identifier) => row[locale] || default_wording(locale, "#{current_key} (#{key_infos.dig(:plural_identifier)})") }
|
82
|
-
elsif key_infos.dig(:numeral_key) == Constant::ADAPTIVE_KEY_SYMBOL
|
83
|
-
trace_wording(row[locale],
|
84
|
-
"[#{locale.upcase}] Adaptive key ---> adaptive_identifier : #{key_infos.dig(:adaptive_identifier)}, key : #{current_key}",
|
85
|
-
"[#{locale.upcase}] Missing translation for #{current_key} (#{key_infos.dig(:adaptive_identifier)})")
|
86
|
-
value = { key_infos.dig(:adaptive_identifier) => row[locale] || default_wording(locale, "#{current_key} (#{key_infos.dig(:adaptive_identifier)})") }
|
87
|
-
elsif key_infos.dig(:numeral_key) == Constant::INFO_PLIST_KEY_SYMBOL
|
88
|
-
trace_wording(row[locale], "[#{locale.upcase}] Info.plist key ---> #{current_key}", "[#{locale.upcase}] Missing translation for #{current_key}")
|
89
|
-
value = row[locale] || default_wording(locale, current_key)
|
90
|
-
else
|
91
|
-
raise "Unknown numeral key #{key_infos.dig(:numeral_key)}"
|
92
|
-
end
|
93
|
-
|
94
|
-
check_wording_parameters(row[locale], locale, current_key)
|
95
|
-
output[current_key][locale.to_sym][key_infos.dig(:numeral_key)] = value
|
96
|
-
locale_comment_column = "#{Constant::COMMENT_KEY_COLUMN_IDENTIFIER} #{locale}"
|
97
|
-
output[current_key][locale.to_sym][Constant::COMMENT_KEY_SYMBOL] = row[locale_comment_column] unless locale_comment_column.blank? and row[locale_comment_column].blank?
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def parse_key(row)
|
102
|
-
key = row.field(CSV_WORDING_KEYS_COLUMN).strip
|
103
|
-
plural_prefix = key.match(PLURAL_KEY_REGEXP)
|
104
|
-
plural_identifier = nil
|
105
|
-
invalid_plural = false
|
106
|
-
|
107
|
-
adaptive_prefix = key.match(ADAPTIVE_KEY_REGEXP)
|
108
|
-
adaptive_identifier = nil
|
109
|
-
invalid_adaptive = false
|
110
|
-
|
111
|
-
if plural_prefix != nil
|
112
|
-
numeral_key = Constant::PLURAL_KEY_SYMBOL
|
113
|
-
key = plural_prefix.pre_match
|
114
|
-
plural_identifier = plural_prefix.captures&.first
|
115
|
-
LOGGER.log(:debug, :red, "Invalid key #{key}") if key.nil?
|
116
|
-
LOGGER.log(:debug, :red, "Empty plural prefix!") if plural_identifier.nil?
|
117
|
-
invalid_plural = plural_identifier.nil?
|
118
|
-
elsif adaptive_prefix != nil
|
119
|
-
numeral_key = Constant::ADAPTIVE_KEY_SYMBOL
|
120
|
-
key = adaptive_prefix.pre_match
|
121
|
-
adaptive_identifier = adaptive_prefix.captures&.first
|
122
|
-
LOGGER.log(:debug, :red, "Invalid key #{key}") if key.nil?
|
123
|
-
LOGGER.log(:debug, :red, "Empty adaptive prefix!") if adaptive_identifier.nil?
|
124
|
-
invalid_adaptive = adaptive_identifier.nil?
|
125
|
-
elsif key.match(INFO_PLIST_KEY_REGEXP) != nil
|
126
|
-
numeral_key = Constant::INFO_PLIST_KEY_SYMBOL
|
127
|
-
else
|
128
|
-
numeral_key = Constant::SINGULAR_KEY_SYMBOL
|
129
|
-
end
|
130
|
-
|
131
|
-
(key.nil? or invalid_plural or invalid_adaptive) ? nil : { key: key.to_sym, numeral_key: numeral_key, plural_identifier: plural_identifier&.to_sym, adaptive_identifier: adaptive_identifier&.to_sym }
|
132
|
-
end
|
133
|
-
|
134
|
-
def default_wording(locale, key)
|
135
|
-
LOGGER.debug? ? "<[#{locale.upcase}] Missing translation for #{key}>" : ""
|
136
|
-
end
|
137
|
-
|
138
|
-
def trace_wording(wording, present_message, missing_message)
|
139
|
-
if wording
|
140
|
-
LOGGER.log(:debug, :green, present_message)
|
141
|
-
else
|
142
|
-
LOGGER.log(:debug, :yellow, missing_message)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
def check_wording_parameters(value, locale, key)
|
147
|
-
formatted_arguments = value&.scan(/%(\d$)?@/) || []
|
148
|
-
if formatted_arguments.size >= 2
|
149
|
-
is_all_ordered = formatted_arguments.inject(true){ |is_ordered, match| is_ordered &&= !match.join.empty? }
|
150
|
-
LOGGER.log(:warn, :red, "[#{locale.upcase}] Multiple arguments for #{key} but no order") unless is_all_ordered
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
def remove_numeral_conflicts!(data)
|
155
|
-
data.select do |_, wording|
|
156
|
-
wording.values.any? { |translation| (translation.keys & [:plural, :singular]).size == 2 }
|
157
|
-
end.keys.each do |key|
|
158
|
-
AdLocalize::LOGGER.log(:warn, :yellow, "Key \"#{key}\" is duplicated in singular and plural." \
|
159
|
-
"The singular wording will be ignored. You should keep one version of the key (singular or plural)"
|
160
|
-
)
|
161
|
-
data[key].values.each { |wording| wording.delete(:singular) }
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
@@ -1,70 +0,0 @@
|
|
1
|
-
module AdLocalize::Platform
|
2
|
-
class AndroidFormatter < PlatformFormatter
|
3
|
-
def platform
|
4
|
-
:android
|
5
|
-
end
|
6
|
-
|
7
|
-
def export(locale, data, export_extension = nil, substitution_format = nil)
|
8
|
-
locale = locale.to_sym
|
9
|
-
export_dir_suffix = (locale == default_locale) ? "" : "-#{locale.downcase}"
|
10
|
-
create_locale_dir(export_dir_suffix)
|
11
|
-
|
12
|
-
xml_doc = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
|
13
|
-
xml.resources {
|
14
|
-
data.each do |key, wording|
|
15
|
-
singular_wording = wording.dig(locale, AdLocalize::Constant::SINGULAR_KEY_SYMBOL)
|
16
|
-
unless singular_wording.blank?
|
17
|
-
comment = wording.dig(locale, AdLocalize::Constant::COMMENT_KEY_SYMBOL)
|
18
|
-
add_singular_wording_to_xml(key, singular_wording, xml, comment: comment)
|
19
|
-
end
|
20
|
-
|
21
|
-
plural_wording = wording.dig(locale, AdLocalize::Constant::PLURAL_KEY_SYMBOL)
|
22
|
-
add_plural_wording_to_xml(key, plural_wording, xml) unless plural_wording.blank?
|
23
|
-
end
|
24
|
-
}
|
25
|
-
end
|
26
|
-
|
27
|
-
export_dir(export_dir_suffix).join(AdLocalize::Constant::ANDROID_EXPORT_FILENAME).open("w") do |file|
|
28
|
-
file.puts xml_doc.to_xml(indent: 4)
|
29
|
-
end
|
30
|
-
AdLocalize::LOGGER.log(:debug, :black, "Android [#{locale}] ---> DONE!")
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def ios_converter(value)
|
36
|
-
processedValue = value.gsub(/(?<!\\)'/, "\\\\'") # match ' unless there is a \ before
|
37
|
-
processedValue = processedValue.gsub(/(?<!\\)\"/, "\\\"") # match " unless there is a \ before
|
38
|
-
processedValue = processedValue.gsub(/(%(\d+\$)?@)/, '%\2s') # should match values like %1$s and %s
|
39
|
-
processedValue = processedValue.gsub(/(%((\d+\$)?(\d+)?)i)/, '%\2d') # should match values like %i, %3$i, %01i, %1$02i
|
40
|
-
processedValue = processedValue.gsub(/%(?!((\d+\$)?(s|(\d+)?d)))/, '%%') # negative lookahead: identifies when user really wants to display a %
|
41
|
-
processedValue = processedValue.gsub("\\U", "\\u")
|
42
|
-
"\"#{processedValue}\""
|
43
|
-
end
|
44
|
-
|
45
|
-
def add_singular_wording_to_xml(key, text, xml, comment: nil)
|
46
|
-
xml.comment(comment) unless comment.blank?
|
47
|
-
xml.string(name: key) {
|
48
|
-
add_wording_text_to_xml(text, xml)
|
49
|
-
}
|
50
|
-
end
|
51
|
-
|
52
|
-
def add_plural_wording_to_xml(key, plural_hash, xml)
|
53
|
-
xml.plurals(name: key) {
|
54
|
-
plural_hash.each do |plural_type, plural_text|
|
55
|
-
next if plural_text.blank?
|
56
|
-
xml.item(quantity: plural_type) {
|
57
|
-
add_wording_text_to_xml(plural_text, xml)
|
58
|
-
}
|
59
|
-
end
|
60
|
-
} unless plural_hash.values.all? &:empty?
|
61
|
-
end
|
62
|
-
|
63
|
-
def add_wording_text_to_xml(wording_text, xml)
|
64
|
-
raise 'Wording text should not be empty' if wording_text.blank?
|
65
|
-
xml.text(
|
66
|
-
ios_converter(wording_text)
|
67
|
-
)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
@@ -1,143 +0,0 @@
|
|
1
|
-
module AdLocalize::Platform
|
2
|
-
class IosFormatter < PlatformFormatter
|
3
|
-
def platform
|
4
|
-
:ios
|
5
|
-
end
|
6
|
-
|
7
|
-
def export(locale, data, export_extension = nil, substitution_format = nil)
|
8
|
-
create_locale_dir(locale)
|
9
|
-
all_symbols = [
|
10
|
-
AdLocalize::Constant::PLURAL_KEY_SYMBOL,
|
11
|
-
AdLocalize::Constant::ADAPTIVE_KEY_SYMBOL,
|
12
|
-
AdLocalize::Constant::SINGULAR_KEY_SYMBOL,
|
13
|
-
AdLocalize::Constant::INFO_PLIST_KEY_SYMBOL
|
14
|
-
]
|
15
|
-
all_symbols.each do |numeral_key|
|
16
|
-
numeral_data = data.select {|key, wording| wording.dig(locale.to_sym)&.key? numeral_key}
|
17
|
-
if numeral_data.empty?
|
18
|
-
AdLocalize::LOGGER.log(:info, :green, "[#{locale.upcase}] no #{numeral_key.to_s} keys were found to generate the file")
|
19
|
-
else
|
20
|
-
send("write_#{numeral_key}", locale, numeral_data)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
protected
|
26
|
-
|
27
|
-
def write_singular(locale, singulars)
|
28
|
-
write_localizable(
|
29
|
-
locale: locale,
|
30
|
-
singulars: singulars,
|
31
|
-
wording_type: AdLocalize::Constant::SINGULAR_KEY_SYMBOL,
|
32
|
-
filename: AdLocalize::Constant::IOS_SINGULAR_EXPORT_FILENAME
|
33
|
-
)
|
34
|
-
end
|
35
|
-
|
36
|
-
def write_info_plist(locale, singulars)
|
37
|
-
write_localizable(
|
38
|
-
locale: locale,
|
39
|
-
singulars: singulars,
|
40
|
-
wording_type: AdLocalize::Constant::INFO_PLIST_KEY_SYMBOL,
|
41
|
-
filename: AdLocalize::Constant::IOS_INFO_PLIST_EXPORT_FILENAME
|
42
|
-
)
|
43
|
-
end
|
44
|
-
|
45
|
-
def write_plural(locale, plurals)
|
46
|
-
locale = locale.to_sym
|
47
|
-
|
48
|
-
append_to_localizable_plist(locale) do |xml|
|
49
|
-
plurals.each do |wording_key, translations|
|
50
|
-
xml.key wording_key
|
51
|
-
xml.dict {
|
52
|
-
xml.key "NSStringLocalizedFormatKey"
|
53
|
-
xml.string "%\#@key@"
|
54
|
-
xml.key "key"
|
55
|
-
xml.dict {
|
56
|
-
xml.key "NSStringFormatSpecTypeKey"
|
57
|
-
xml.string "NSStringPluralRuleType"
|
58
|
-
xml.key "NSStringFormatValueTypeKey"
|
59
|
-
xml.string "d"
|
60
|
-
translations[locale][AdLocalize::Constant::PLURAL_KEY_SYMBOL].each do |wording_type, wording_value|
|
61
|
-
xml.key wording_type
|
62
|
-
xml.string wording_value
|
63
|
-
end
|
64
|
-
}
|
65
|
-
}
|
66
|
-
end
|
67
|
-
end
|
68
|
-
AdLocalize::LOGGER.log(:debug, :green, "iOS plural [#{locale}] ---> DONE!")
|
69
|
-
end
|
70
|
-
|
71
|
-
def write_adaptive(locale, adaptives)
|
72
|
-
locale = locale.to_sym
|
73
|
-
|
74
|
-
append_to_localizable_plist(locale) do |xml|
|
75
|
-
adaptives.each do |wording_key, translations|
|
76
|
-
xml.key wording_key
|
77
|
-
xml.dict {
|
78
|
-
xml.key "NSStringVariableWidthRuleType"
|
79
|
-
xml.dict {
|
80
|
-
translations[locale][AdLocalize::Constant::ADAPTIVE_KEY_SYMBOL].each do |wording_type, wording_value|
|
81
|
-
xml.key wording_type
|
82
|
-
xml.string wording_value
|
83
|
-
end
|
84
|
-
}
|
85
|
-
}
|
86
|
-
end
|
87
|
-
end
|
88
|
-
AdLocalize::LOGGER.log(:debug, :black, "iOS adaptive [#{locale}] ---> DONE!")
|
89
|
-
end
|
90
|
-
|
91
|
-
private
|
92
|
-
|
93
|
-
def escape_quotes_if_needed(value)
|
94
|
-
value.gsub(/(?<!\\)\"/, "\\\"") # match " unless there is a \ before
|
95
|
-
end
|
96
|
-
|
97
|
-
def write_localizable(locale:, singulars:, wording_type:, filename:)
|
98
|
-
locale = locale.to_sym
|
99
|
-
|
100
|
-
singulars.each do |key, locales_wording|
|
101
|
-
value = locales_wording.dig(locale, wording_type)
|
102
|
-
value = escape_quotes_if_needed(value)
|
103
|
-
comment = locales_wording.dig(locale, AdLocalize::Constant::COMMENT_KEY_SYMBOL)
|
104
|
-
export_dir(locale).join(filename).open("a") do |file|
|
105
|
-
line = ""
|
106
|
-
if wording_type == AdLocalize::Constant::INFO_PLIST_KEY_SYMBOL
|
107
|
-
line = %(#{key} = "#{value}";)
|
108
|
-
else
|
109
|
-
line = %("#{key}" = "#{value}";)
|
110
|
-
end
|
111
|
-
line << " // #{comment}" unless comment.nil?
|
112
|
-
line << "\n"
|
113
|
-
file.puts line
|
114
|
-
end
|
115
|
-
end
|
116
|
-
AdLocalize::LOGGER.log(:debug, :green, "iOS #{wording_type} [#{locale}] ---> DONE!")
|
117
|
-
end
|
118
|
-
|
119
|
-
def append_to_localizable_plist(locale)
|
120
|
-
filename = export_dir(locale).join(AdLocalize::Constant::IOS_PLURAL_EXPORT_FILENAME)
|
121
|
-
xml_doc = nil
|
122
|
-
if File.exist?(filename)
|
123
|
-
xml_content = Nokogiri::XML(open(filename)) do |config|
|
124
|
-
config.default_xml.noblanks # minimify xml
|
125
|
-
end
|
126
|
-
xml_doc = Nokogiri::XML::Builder.with(xml_content.css('plist>dict').first) do |xml|
|
127
|
-
yield(xml)
|
128
|
-
end
|
129
|
-
else
|
130
|
-
xml_doc = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
|
131
|
-
xml.plist {
|
132
|
-
xml.dict {
|
133
|
-
yield(xml)
|
134
|
-
}
|
135
|
-
}
|
136
|
-
end
|
137
|
-
end
|
138
|
-
filename.open("w") do |file|
|
139
|
-
file.puts xml_doc.to_xml(indent: 4)
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module AdLocalize::Platform
|
2
|
-
class JsonFormatter < PlatformFormatter
|
3
|
-
def platform
|
4
|
-
:json
|
5
|
-
end
|
6
|
-
|
7
|
-
def export(locale, data, export_extension = "json", substitution_format = "react")
|
8
|
-
locale = locale.to_sym
|
9
|
-
json_data = build_platform_data_splitting_on_dots(locale, data)
|
10
|
-
platform_dir.join("#{locale.to_s}.#{export_extension}").open("w") do |file|
|
11
|
-
file.puts json_data.to_json
|
12
|
-
end
|
13
|
-
|
14
|
-
AdLocalize::LOGGER.log(:debug, :green, "JSON [#{locale}] ---> DONE!")
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,109 +0,0 @@
|
|
1
|
-
module AdLocalize::Platform
|
2
|
-
class PlatformFormatter
|
3
|
-
PLURAL_KEY_SYMBOL = :plural
|
4
|
-
SINGULAR_KEY_SYMBOL = :singular
|
5
|
-
OPTIONS = {output_path: ".."}
|
6
|
-
|
7
|
-
attr_accessor :platform_dir
|
8
|
-
attr_reader :default_locale, :output_path, :add_intermediate_platform_dir
|
9
|
-
|
10
|
-
def initialize(default_locale, output_path, add_intermediate_platform_dir)
|
11
|
-
@default_locale = default_locale.to_sym
|
12
|
-
@output_path = output_path # Must be set before platform_dir
|
13
|
-
@platform_dir = add_intermediate_platform_dir ? export_base_directory.join(platform.to_s) : export_base_directory
|
14
|
-
@add_intermediate_platform_dir = add_intermediate_platform_dir
|
15
|
-
create_platform_dir
|
16
|
-
end
|
17
|
-
|
18
|
-
def platform
|
19
|
-
raise 'Please override me!'
|
20
|
-
end
|
21
|
-
|
22
|
-
def export(locale, data, export_extension, substitution_format)
|
23
|
-
locale = locale.to_sym
|
24
|
-
formatted_data = data.each_with_object({}) do |(key, wording), hash_acc|
|
25
|
-
hash_acc[locale.to_s] = {} unless hash_acc.key? locale.to_s
|
26
|
-
if wording.dig(locale)&.key? :singular
|
27
|
-
value = ios_converter(wording.dig(locale, :singular))
|
28
|
-
hash_acc[locale.to_s][key.to_s] = value
|
29
|
-
end
|
30
|
-
if wording.dig(locale)&.key? :plural
|
31
|
-
hash_acc[locale.to_s][key.to_s] = {}
|
32
|
-
wording.dig(locale, :plural).each do |plural_type, plural_text|
|
33
|
-
value = ios_converter(plural_text)
|
34
|
-
hash_acc[locale.to_s][key.to_s][plural_type.to_s] = value
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
platform_dir.join("#{locale.to_s}.#{export_extension}").open("w") do |file|
|
40
|
-
yield(formatted_data, file)
|
41
|
-
end
|
42
|
-
|
43
|
-
AdLocalize::LOGGER.log(:debug, :green, "#{platform.to_s.upcase} [#{locale}] ---> DONE!")
|
44
|
-
end
|
45
|
-
|
46
|
-
protected
|
47
|
-
def export_base_directory
|
48
|
-
if output_path
|
49
|
-
Pathname.new(output_path)
|
50
|
-
else
|
51
|
-
Pathname::pwd.join(AdLocalize::Constant::EXPORT_FOLDER)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def create_platform_dir
|
56
|
-
if platform_dir.directory? && add_intermediate_platform_dir
|
57
|
-
FileUtils.rm_rf("#{platform_dir}/.", secure: true)
|
58
|
-
else
|
59
|
-
platform_dir.mkpath
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def export_dir(locale)
|
64
|
-
platform_dir + AdLocalize::Constant::CONFIG.dig(:platforms, :export_directory_names, platform.to_sym) % { locale: locale.downcase }
|
65
|
-
end
|
66
|
-
|
67
|
-
def create_locale_dir(locale)
|
68
|
-
raise 'Locale needed' unless locale
|
69
|
-
|
70
|
-
if export_dir(locale).directory?
|
71
|
-
FileUtils.rm_rf("#{export_dir(locale)}/.", secure: true)
|
72
|
-
else
|
73
|
-
export_dir(locale).mkdir
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def build_platform_data_splitting_on_dots(locale, data)
|
78
|
-
data.each_with_object({}) do |(key, wording), hash_acc|
|
79
|
-
hash_acc[locale.to_s] = {} unless hash_acc.key? locale.to_s
|
80
|
-
keys = key.to_s.split('.')
|
81
|
-
hash = hash_acc[locale.to_s]
|
82
|
-
keys.each_with_index do |inner_key, index|
|
83
|
-
if index === keys.count - 1
|
84
|
-
fill_hash(wording, locale, hash, inner_key)
|
85
|
-
else
|
86
|
-
if hash[inner_key].nil?
|
87
|
-
hash[inner_key] = {}
|
88
|
-
end
|
89
|
-
hash = hash[inner_key]
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def fill_hash(wording, locale, hash, key)
|
96
|
-
if wording.dig(locale)&.key? :singular
|
97
|
-
value = wording.dig(locale, :singular)
|
98
|
-
hash[key.to_s] = value
|
99
|
-
end
|
100
|
-
if wording.dig(locale)&.key? :plural
|
101
|
-
hash[key.to_s] = {}
|
102
|
-
wording.dig(locale, :plural).each do |plural_type, plural_text|
|
103
|
-
value = plural_text
|
104
|
-
hash[key.to_s][plural_type.to_s] = value
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|