Class: Fastlane::Actions::IosExtractKeysFromStringsFilesAction

Inherits:
Action
  • Object
show all
Defined in:
lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_extract_keys_from_strings_files.rb

Documentation collapse

Class Method Summary collapse

Class Method Details

.authorsObject



129
130
131
# File 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_extract_keys_from_strings_files.rb', line 129

def self.authors
  ['Automattic']
end

.available_optionsObject



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_extract_keys_from_strings_files.rb', line 89

def self.available_options
  [
    FastlaneCore::ConfigItem.new(key: :source_parent_dir,
                                 env_name: 'FL_IOS_EXTRACT_KEYS_FROM_STRINGS_FILES_SOURCE_PARENT_DIR',
                                 description: 'The parent directory containing all the `*.lproj` subdirectories in which the source `.strings` files reside',
                                 type: String,
                                 verify_block: proc do |value|
                                   UI.user_error!("`source_parent_dir` should be a path to an existing directory, but found `#{value}`.") unless File.directory?(value)
                                   UI.user_error!("`source_parent_dir` should contain at least one `.lproj` subdirectory, but `#{value}` does not contain any.") if Dir.glob('*.lproj', base: value).empty?
                                 end),
    FastlaneCore::ConfigItem.new(key: :source_tablename,
                                 env_name: 'FL_IOS_EXTRACT_KEYS_FROM_STRINGS_FILES_SOURCE_TABLENAME',
                                 description: 'The basename of the `.strings` file (without the extension) to extract the keys and translations from for each locale',
                                 type: String,
                                 default_value: 'Localizable'),
    FastlaneCore::ConfigItem.new(key: :target_original_files,
                                 env_name: 'FL_IOS_EXTRACT_KEYS_FROM_STRINGS_FILES_TARGET_ORIGINAL_FILES',
                                 description: 'The path(s) to the `<base-locale>.lproj/<target-tablename>.strings` file(s) for which we want to extract the keys to, and the prefix to remove from their keys. ' \
                                  + 'Each key in the Hash should point to a file containing the original strings (typically `en` or `Base` locale), and will be used to determine which keys to extract from the `source_tablename`. ' \
                                  + 'For each key, the associated value is an optional prefix to remove from the keys (which can be useful if you used a prefix during `ios_merge_strings_files` to avoid duplicates). Can be nil or empty if no prefix was used during merge for that file.' \
                                  + 'Note: For each entry, the path(s) in which the translations will be extracted to will be the files with the same basename as the key in each of the other `*.lproj` sibling folders. ',
                                 type: Hash,
                                 verify_block: proc do |values|
                                   UI.user_error!('`target_original_files` must contain at least one path to an original `.strings` file.') if values.empty?
                                   values.each_key do |path|
                                     UI.user_error!("Path `#{path}` (found in `target_original_files`) does not exist.") unless File.exist?(path)
                                     UI.user_error! "Expected `#{path}` (found in `target_original_files`) to be a path ending in a `*.lproj/*.strings`." unless File.extname(path) == '.strings' && File.extname(File.dirname(path)) == '.lproj'
                                   end
                                 end),
  ]
end

.descriptionObject



71
72
73
# File 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_extract_keys_from_strings_files.rb', line 71

def self.description
  'Extracts a subset of keys from a `.strings` file into separate `.strings` file(s)'
end

.detailsObject



75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_extract_keys_from_strings_files.rb', line 75

def self.details
  "    Extracts a subset of keys from a `.strings` file into separate `.strings` file(s), for each `*.lproj` subdirectory.\n\n    This is especially useful to extract, for each locale, the translations for files like `InfoPlist.strings` or\n    `<SomeIntentDefinitionFile>.strings` from the `Localizable.strings` file that we exported/downloaded back from GlotPress.\n\n    Since we typically merge all `*.strings` original files (e.g. `en.lproj/Localizable.strings` + `en.lproj/InfoPlist.strings` + \u2026)\n    via `ios_merge_strings_file` before sending the originals to translations, we then need to extract the relevant keys and\n    translations back into the `*.lproj/InfoPlist.strings` after we pull those translations back from GlotPress\n    (`ios_download_strings_files_from_glotpress`). This is what this `ios_extract_keys_from_strings_files` action is for.\n  DETAILS\nend\n"

.is_supported?(platform) ⇒ Boolean

Returns:

  • (Boolean)


133
134
135
# File 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_extract_keys_from_strings_files.rb', line 133

def self.is_supported?(platform)
  i[ios mac].include?(platform)
end

.keys_list_per_target_file(original_files) ⇒ Hash<String, Array<String>>

Pre-load the list of keys to extract for each target file.

Parameters:

  • original_files (Array<String>)

    array of paths to the originals of target files

Returns:

  • (Hash<String, Array<String>>)

    The hash listing the keys to extract for each target file



49
50
51
52
53
54
55
56
# File 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_extract_keys_from_strings_files.rb', line 49

def self.keys_list_per_target_file(original_files)
  original_files.to_h do |original_file|
    keys = Fastlane::Helper::Ios::L10nHelper.read_strings_file_as_hash(path: original_file).keys
    [original_file, keys]
  end
rescue StandardError => e
  UI.user_error!("Failed to read the keys to extract from originals file: #{e.message}")
end

.replace_lproj_in_path(path, with_lproj:) ⇒ Object

Replaces the ‘*.lproj` component of the path to a `.strings` file with a different `.lproj` folder

Parameters:

  • path (String)

    The path the the ‘.strings` file, assumed to be in a `.lproj` parent folder

  • with_lproj (String)

    The new name of the ‘.lproj` parent folder to point to



63
64
65
# File 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_extract_keys_from_strings_files.rb', line 63

def self.replace_lproj_in_path(path, with_lproj:)
  File.join(File.dirname(path, 2), with_lproj, File.basename(path))
end

.return_typeObject



121
122
123
# File 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_extract_keys_from_strings_files.rb', line 121

def self.return_type
  :array_of_strings
end

.return_valueObject



125
126
127
# File 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_extract_keys_from_strings_files.rb', line 125

def self.return_value
  'The list of files which have been generated and written to disk by the action'
end

.run(params) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_extract_keys_from_strings_files.rb', line 6

def self.run(params)
  source_parent_dir = params[:source_parent_dir]
  target_original_files = params[:target_original_files].keys # Array [original-file-paths]
  keys_to_extract_per_target_file = keys_list_per_target_file(target_original_files) # Hash { original-file-path => [keys] }
  prefix_to_remove_per_target_file = params[:target_original_files] # Hash { original-file-path => prefix }

  UI.message("Extracting keys from `#{source_parent_dir}/*.lproj/#{params[:source_tablename]}.strings` into:")
  target_original_files.each { |f| UI.message(' - ' + replace_lproj_in_path(f, with_lproj: '*.lproj')) }

  updated_files_list = []

  # For each locale, extract the right translations from `<source_tablename>.strings` into each target `.strings` file
  Dir.glob('*.lproj', base: source_parent_dir).each do |lproj_dir_name|
    source_strings_file = File.join(source_parent_dir, lproj_dir_name, "#{params[:source_tablename]}.strings")
    translations = Fastlane::Helper::Ios::L10nHelper.read_strings_file_as_hash(path: source_strings_file)

    target_original_files.each do |target_original_file|
      target_strings_file = replace_lproj_in_path(target_original_file, with_lproj: lproj_dir_name)
      next if target_strings_file == target_original_file # do not generate/overwrite the original locale itself

      keys_prefix = prefix_to_remove_per_target_file[target_original_file] || ''
      keys_to_extract = keys_to_extract_per_target_file[target_original_file].map { |k| "#{keys_prefix}#{k}" }
      extracted_translations = translations.slice(*keys_to_extract).transform_keys { |k| k.delete_prefix(keys_prefix) }
      UI.verbose("Extracting #{extracted_translations.count} keys (out of #{keys_to_extract.count} expected) into #{target_strings_file}...")

      FileUtils.mkdir_p(File.dirname(target_strings_file)) # Ensure path up to parent dir exists, create it if not.
      Fastlane::Helper::Ios::L10nHelper.generate_strings_file_from_hash(translations: extracted_translations, output_path: target_strings_file)
      updated_files_list.append(target_strings_file)
    rescue StandardError => e
      UI.user_error!("Error while writing extracted translations to `#{target_strings_file}`: #{e.message}")
    end
  rescue StandardError => e
    UI.user_error!("Error while reading the translations from source file `#{source_strings_file}`: #{e.message}")
  end

  updated_files_list
end