From 703e5b2b93fd300d79adad570754514b8443fad0 Mon Sep 17 00:00:00 2001 From: Olivier Halligon <olivier.halligon@automattic.com> Date: Tue, 10 Aug 2021 18:53:57 +0200 Subject: [PATCH 01/10] Initial implementation for Locale models (WIP) Still requires: - Completing the list of ALL_KNOWN_LOCALES - Enabling from_ios and from_app_store family of tests once we have the values --- lib/fastlane/plugin/wpmreleasetoolkit.rb | 2 +- .../wpmreleasetoolkit/models/locales.rb | 129 ++++++++++++++++++ spec/locales_spec.rb | 105 ++++++++++++++ 3 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb create mode 100644 spec/locales_spec.rb diff --git a/lib/fastlane/plugin/wpmreleasetoolkit.rb b/lib/fastlane/plugin/wpmreleasetoolkit.rb index dad7c7064..a1128823c 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit.rb @@ -4,7 +4,7 @@ module Fastlane module Wpmreleasetoolkit # Return all .rb files inside the "actions" and "helper" directory def self.all_classes - Dir[File.expand_path('**/{actions,helper}/**/*.rb', File.dirname(__FILE__))] + Dir[File.expand_path('**/{actions,helper,models}/**/*.rb', File.dirname(__FILE__))] end end end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb b/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb new file mode 100644 index 000000000..9381d8fd6 --- /dev/null +++ b/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb @@ -0,0 +1,129 @@ +module Fastlane + Locale = Struct.new(:glotpress, :android, :google_play, :ios, :app_store, keyword_init: true) do + def self.[](code) + Locales[code].first + end + end + + class Locales + + ################### + ## Constants + ALL_KNOWN_LOCALES = [ + Locale.new(glotpress: "ar", android: "ar", google_play: "ar" ), + Locale.new(glotpress: "de", android: "de", google_play: "de-DE"), + Locale.new(glotpress: "en-gb", android: "en-rGB", google_play: "en-US"), + Locale.new(glotpress: "es", android: "es", google_play: "es-ES"), + Locale.new(glotpress: "fr-ca", android: "fr-rCA", google_play: "fr-CA"), + Locale.new(glotpress: "fr", android: "fr", google_play: "fr-FR"), + Locale.new(glotpress: "he", android: "he", google_play: "iw-IL"), + Locale.new(glotpress: "id", android: "id", google_play: "id" ), + Locale.new(glotpress: "it", android: "it", google_play: "it-IT"), + Locale.new(glotpress: "ja", android: "ja", google_play: "ja-JP"), + Locale.new(glotpress: "ko", android: "ko", google_play: "ko-KR"), + Locale.new(glotpress: "nl", android: "nl", google_play: "nl-NL"), + Locale.new(glotpress: "pl", android: "pl", google_play: "pl-PL"), + Locale.new(glotpress: "pt-br", android: "pt-rBR", google_play: "pt-BR"), + Locale.new(glotpress: "ru", android: "ru", google_play: "ru-RU"), + Locale.new(glotpress: "sr", android: "sr", google_play: "sr" ), + Locale.new(glotpress: "sv", android: "sv", google_play: "sv-SE"), + Locale.new(glotpress: "th", android: "th", google_play: "th" ), + Locale.new(glotpress: "tr", android: "tr", google_play: "tr-TR"), + Locale.new(glotpress: "vi", android: "vi", google_play: "vi" ), + Locale.new(glotpress: "zh-cn", android: "zh-rCN", google_play: "zh-CN"), + Locale.new(glotpress: "zh-tw", android: "zh-rTW", google_play: "zh-TW"), + Locale.new(glotpress: "az", android: "az"), + Locale.new(glotpress: "el", android: "el"), + Locale.new(glotpress: "es-mx", android: "es-rMX"), + Locale.new(glotpress: "es-cl", android: "es-rCL"), + Locale.new(glotpress: "gd", android: "gd"), + Locale.new(glotpress: "hi", android: "hi"), + Locale.new(glotpress: "hu", android: "hu"), + Locale.new(glotpress: "nb", android: "nb"), + Locale.new(glotpress: "pl", android: "pl"), + Locale.new(glotpress: "th", android: "th"), + Locale.new(glotpress: "uz", android: "uz"), + Locale.new(glotpress: "zh-tw", android: "zh-rHK"), + Locale.new(glotpress: "eu", android: "eu"), + Locale.new(glotpress: "ro", android: "ro"), + Locale.new(glotpress: "mk", android: "mk"), + Locale.new(glotpress: "en-au", android: "en-rAU"), + Locale.new(glotpress: "sr", android: "sr"), + Locale.new(glotpress: "sk", android: "sk"), + Locale.new(glotpress: "cy", android: "cy"), + Locale.new(glotpress: "da", android: "da"), + Locale.new(glotpress: "bg", android: "bg"), + Locale.new(glotpress: "sq", android: "sq"), + Locale.new(glotpress: "hr", android: "hr"), + Locale.new(glotpress: "cs", android: "cs"), + Locale.new(glotpress: "pt-br", android: "pt-rBR"), + Locale.new(glotpress: "en-ca", android: "en-rCA"), + Locale.new(glotpress: "ms", android: "ms"), + Locale.new(glotpress: "es-ve", android: "es-rVE"), + Locale.new(glotpress: "gl", android: "gl"), + Locale.new(glotpress: "is", android: "is"), + Locale.new(glotpress: "es-co", android: "es-rCO"), + Locale.new(glotpress: "kmr", android: "kmr") + ].freeze + + MAG16_GP_CODES = %w[ar de es fr he id it ja ko nl pt-br ru sv tr zh-cn zh-tw].freeze + + ################### + ## Static Methods + + class << self + + # @return [Array<Locale>] Array of all the known locales + # + def all + ALL_KNOWN_LOCALES + end + + # Define from_glotpress(code_or_list), from_android(code_or_list) … methods + # + # @param [Array<String>, String] list of locale codes to search for, or single value for single result + # @return [Array<Locale>, Locale] list of found locales (empty if none found), or single locale if a single value was passed (or nil if not found) + # + %i[glotpress android google_play ios app_store].each do |key| + define_method("from_#{key}") { |args| search(key, args) } + end + + # Return an Array<Locale> based on glotpress locale codes + # + # @note If you need a single locale, you can use Locale[code] instead of Locales[code] + # @param [String..., Array<String>] Arbitrary list of strings, either passed as a single array parameter, or as a vararg list of params + # @return [Array<Locale>] The found locales. + # + def [](*list) + # If we passed an Array, `*list` will make it an Array<Array<String>>, so taking `list.first` in those cases to go back to Array<String> + list = list.first if list.count == 1 && list.first.is_a?(Array) + from_glotpress(list) + end + + # Return the subset of the 16 locales most of our apps are localized 100% (what we call the "Magnificent 16") + # + # @return [Array<Locale>] List of the Mag16 locales + def mag16 + from_glotpress(MAG16_GP_CODES) + end + + ################### + + private + + # Search the known locales for just the ones having the provided locale code, where the codes are expressed using the standard for the given key + def search(key, code_or_list) + if code_or_list.is_a?(Array) + code_or_list.map { |code| search(key, code) } + else # String + raise 'The locale code should not contain spaces. Did you accidentally use `%[]` instead of `%w[]` at call site?' if code_or_list.include?(' ') + ALL_KNOWN_LOCALES.find { |locale| locale.send(key) == code_or_list } || not_found(code_or_list, key) + end + end + + def not_found(code, key) + raise "Unknown locale for #{key} code '#{code}'" + end + end + end +end diff --git a/spec/locales_spec.rb b/spec/locales_spec.rb new file mode 100644 index 000000000..84a32cac4 --- /dev/null +++ b/spec/locales_spec.rb @@ -0,0 +1,105 @@ +require 'spec_helper' + +describe Fastlane::Locale do + it 'returns a single Locale if one was found' do + locale = Fastlane::Locale['fr'] + expect(locale).to be_instance_of(Fastlane::Locale) + expect(locale.glotpress).to eq('fr') + end + + it 'raises if no locale was found for a given code' do + expect { + Fastlane::Locale['invalidcode'] + }.to raise_error(RuntimeError, "Unknown locale for glotpress code 'invalidcode'") + end +end + +describe Fastlane::Locales do + shared_examples 'from_xxx' do |key, fr_code, pt_code| + let(:method_sym) { "from_#{key}".to_sym } + it 'can find a locale from a single code' do + fr_locale = Fastlane::Locales.send(method_sym, fr_code) + expect(fr_locale).to be_instance_of(Fastlane::Locale) + expect(fr_locale.glotpress).to eq('fr') + expect(fr_locale.android).to eq('fr') + expect(fr_locale.google_play).to eq('fr-FR') + end + + it 'can find locales from a multiple codes' do + locales = Fastlane::Locales.send(method_sym, [fr_code, pt_code]) + expect(locales).to be_instance_of(Array) + + expect(locales[0]).to be_instance_of(Fastlane::Locale) + expect(locales[0].glotpress).to eq('fr') + + expect(locales[1]).to be_instance_of(Fastlane::Locale) + expect(locales[1].glotpress).to eq('pt-br') + end + + it 'raises if one of the locale codes passed was not found' do + expect { + Fastlane::Locales.send(method_sym, [fr_code, 'invalidcode', 'pt-br']) + }.to raise_error(RuntimeError, "Unknown locale for #{key} code 'invalidcode'") + end + end + + describe 'from_glotpress' do + include_examples 'from_xxx', :glotpress, 'fr', 'pt-br' + end + + describe 'from_android' do + include_examples 'from_xxx', :android, 'fr', 'pt-rBR' + end + + describe 'from_google_play' do + include_examples 'from_xxx', :google_play, 'fr-FR', 'pt-BR' + end + + # @TODO: from_ios, from_app_store + + describe 'subscript [] operator' do + it 'returns an Array<Locale> even if a single one was passed' do + locales = Fastlane::Locales['fr'] + expect(locales).to be_instance_of(Array) + expect(locales.count).to equal(1) + expect(locales[0].glotpress).to eq('fr') + end + + it 'returns an Array<Locale> if a list of vararg codes was passed' do + locales = Fastlane::Locales['fr', 'pt-br'] + expect(locales).to be_instance_of(Array) + expect(locales.count).to equal(2) + expect(locales[0]).to be_instance_of(Fastlane::Locale) + expect(locales[0].glotpress).to eq('fr') + expect(locales[1]).to be_instance_of(Fastlane::Locale) + expect(locales[1].glotpress).to eq('pt-br') + end + + it 'returns an Array<Locale> if an Array<String> of codes was passed' do + list = %w[fr pt-br] + locales = Fastlane::Locales[list] + expect(locales).to be_instance_of(Array) + expect(locales.count).to equal(2) + expect(locales[0]).to be_instance_of(Fastlane::Locale) + expect(locales[0].glotpress).to eq('fr') + expect(locales[1]).to be_instance_of(Fastlane::Locale) + expect(locales[1].glotpress).to eq('pt-br') + end + end + + it 'returns exactly 16 Mag16 locales' do + expect(Fastlane::Locales.mag16.count).to eq(16) + end + + it 'is easy to do Locale subset intersections' do + mag16_except_pt = Fastlane::Locales.mag16 - Fastlane::Locales['pt-br'] + expect(mag16_except_pt.count).to equal(15) + expect(mag16_except_pt.find { |l| l.glotpress == 'pt-br' }).to be_nil + expect(mag16_except_pt.find { |l| l.glotpress == 'fr' }).to_not be_nil + end + + it 'can convert a Locale to a hash' do + h = Fastlane::Locale['fr'].to_h + expect(h).to eq({ glotpress: 'fr', android: 'fr', google_play: 'fr-FR', ios: nil, app_store: nil }) + end +end From 0bcd9619f8d0c50fa90030fffa22a659a7c21fd0 Mon Sep 17 00:00:00 2001 From: Olivier Halligon <olivier.halligon@automattic.com> Date: Tue, 10 Aug 2021 19:13:44 +0200 Subject: [PATCH 02/10] Fix rubocop violations --- .../wpmreleasetoolkit/models/locales.rb | 111 +++++++++--------- spec/locales_spec.rb | 10 +- 2 files changed, 60 insertions(+), 61 deletions(-) diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb b/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb index 9381d8fd6..4588c160f 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb @@ -6,64 +6,63 @@ def self.[](code) end class Locales - ################### ## Constants ALL_KNOWN_LOCALES = [ - Locale.new(glotpress: "ar", android: "ar", google_play: "ar" ), - Locale.new(glotpress: "de", android: "de", google_play: "de-DE"), - Locale.new(glotpress: "en-gb", android: "en-rGB", google_play: "en-US"), - Locale.new(glotpress: "es", android: "es", google_play: "es-ES"), - Locale.new(glotpress: "fr-ca", android: "fr-rCA", google_play: "fr-CA"), - Locale.new(glotpress: "fr", android: "fr", google_play: "fr-FR"), - Locale.new(glotpress: "he", android: "he", google_play: "iw-IL"), - Locale.new(glotpress: "id", android: "id", google_play: "id" ), - Locale.new(glotpress: "it", android: "it", google_play: "it-IT"), - Locale.new(glotpress: "ja", android: "ja", google_play: "ja-JP"), - Locale.new(glotpress: "ko", android: "ko", google_play: "ko-KR"), - Locale.new(glotpress: "nl", android: "nl", google_play: "nl-NL"), - Locale.new(glotpress: "pl", android: "pl", google_play: "pl-PL"), - Locale.new(glotpress: "pt-br", android: "pt-rBR", google_play: "pt-BR"), - Locale.new(glotpress: "ru", android: "ru", google_play: "ru-RU"), - Locale.new(glotpress: "sr", android: "sr", google_play: "sr" ), - Locale.new(glotpress: "sv", android: "sv", google_play: "sv-SE"), - Locale.new(glotpress: "th", android: "th", google_play: "th" ), - Locale.new(glotpress: "tr", android: "tr", google_play: "tr-TR"), - Locale.new(glotpress: "vi", android: "vi", google_play: "vi" ), - Locale.new(glotpress: "zh-cn", android: "zh-rCN", google_play: "zh-CN"), - Locale.new(glotpress: "zh-tw", android: "zh-rTW", google_play: "zh-TW"), - Locale.new(glotpress: "az", android: "az"), - Locale.new(glotpress: "el", android: "el"), - Locale.new(glotpress: "es-mx", android: "es-rMX"), - Locale.new(glotpress: "es-cl", android: "es-rCL"), - Locale.new(glotpress: "gd", android: "gd"), - Locale.new(glotpress: "hi", android: "hi"), - Locale.new(glotpress: "hu", android: "hu"), - Locale.new(glotpress: "nb", android: "nb"), - Locale.new(glotpress: "pl", android: "pl"), - Locale.new(glotpress: "th", android: "th"), - Locale.new(glotpress: "uz", android: "uz"), - Locale.new(glotpress: "zh-tw", android: "zh-rHK"), - Locale.new(glotpress: "eu", android: "eu"), - Locale.new(glotpress: "ro", android: "ro"), - Locale.new(glotpress: "mk", android: "mk"), - Locale.new(glotpress: "en-au", android: "en-rAU"), - Locale.new(glotpress: "sr", android: "sr"), - Locale.new(glotpress: "sk", android: "sk"), - Locale.new(glotpress: "cy", android: "cy"), - Locale.new(glotpress: "da", android: "da"), - Locale.new(glotpress: "bg", android: "bg"), - Locale.new(glotpress: "sq", android: "sq"), - Locale.new(glotpress: "hr", android: "hr"), - Locale.new(glotpress: "cs", android: "cs"), - Locale.new(glotpress: "pt-br", android: "pt-rBR"), - Locale.new(glotpress: "en-ca", android: "en-rCA"), - Locale.new(glotpress: "ms", android: "ms"), - Locale.new(glotpress: "es-ve", android: "es-rVE"), - Locale.new(glotpress: "gl", android: "gl"), - Locale.new(glotpress: "is", android: "is"), - Locale.new(glotpress: "es-co", android: "es-rCO"), - Locale.new(glotpress: "kmr", android: "kmr") + Locale.new(glotpress: 'ar', android: 'ar', google_play: 'ar'), + Locale.new(glotpress: 'de', android: 'de', google_play: 'de-DE'), + Locale.new(glotpress: 'en-gb', android: 'en-rGB', google_play: 'en-US'), + Locale.new(glotpress: 'es', android: 'es', google_play: 'es-ES'), + Locale.new(glotpress: 'fr-ca', android: 'fr-rCA', google_play: 'fr-CA'), + Locale.new(glotpress: 'fr', android: 'fr', google_play: 'fr-FR'), + Locale.new(glotpress: 'he', android: 'he', google_play: 'iw-IL'), + Locale.new(glotpress: 'id', android: 'id', google_play: 'id'), + Locale.new(glotpress: 'it', android: 'it', google_play: 'it-IT'), + Locale.new(glotpress: 'ja', android: 'ja', google_play: 'ja-JP'), + Locale.new(glotpress: 'ko', android: 'ko', google_play: 'ko-KR'), + Locale.new(glotpress: 'nl', android: 'nl', google_play: 'nl-NL'), + Locale.new(glotpress: 'pl', android: 'pl', google_play: 'pl-PL'), + Locale.new(glotpress: 'pt-br', android: 'pt-rBR', google_play: 'pt-BR'), + Locale.new(glotpress: 'ru', android: 'ru', google_play: 'ru-RU'), + Locale.new(glotpress: 'sr', android: 'sr', google_play: 'sr'), + Locale.new(glotpress: 'sv', android: 'sv', google_play: 'sv-SE'), + Locale.new(glotpress: 'th', android: 'th', google_play: 'th'), + Locale.new(glotpress: 'tr', android: 'tr', google_play: 'tr-TR'), + Locale.new(glotpress: 'vi', android: 'vi', google_play: 'vi'), + Locale.new(glotpress: 'zh-cn', android: 'zh-rCN', google_play: 'zh-CN'), + Locale.new(glotpress: 'zh-tw', android: 'zh-rTW', google_play: 'zh-TW'), + Locale.new(glotpress: 'az', android: 'az'), + Locale.new(glotpress: 'el', android: 'el'), + Locale.new(glotpress: 'es-mx', android: 'es-rMX'), + Locale.new(glotpress: 'es-cl', android: 'es-rCL'), + Locale.new(glotpress: 'gd', android: 'gd'), + Locale.new(glotpress: 'hi', android: 'hi'), + Locale.new(glotpress: 'hu', android: 'hu'), + Locale.new(glotpress: 'nb', android: 'nb'), + Locale.new(glotpress: 'pl', android: 'pl'), + Locale.new(glotpress: 'th', android: 'th'), + Locale.new(glotpress: 'uz', android: 'uz'), + Locale.new(glotpress: 'zh-tw', android: 'zh-rHK'), + Locale.new(glotpress: 'eu', android: 'eu'), + Locale.new(glotpress: 'ro', android: 'ro'), + Locale.new(glotpress: 'mk', android: 'mk'), + Locale.new(glotpress: 'en-au', android: 'en-rAU'), + Locale.new(glotpress: 'sr', android: 'sr'), + Locale.new(glotpress: 'sk', android: 'sk'), + Locale.new(glotpress: 'cy', android: 'cy'), + Locale.new(glotpress: 'da', android: 'da'), + Locale.new(glotpress: 'bg', android: 'bg'), + Locale.new(glotpress: 'sq', android: 'sq'), + Locale.new(glotpress: 'hr', android: 'hr'), + Locale.new(glotpress: 'cs', android: 'cs'), + Locale.new(glotpress: 'pt-br', android: 'pt-rBR'), + Locale.new(glotpress: 'en-ca', android: 'en-rCA'), + Locale.new(glotpress: 'ms', android: 'ms'), + Locale.new(glotpress: 'es-ve', android: 'es-rVE'), + Locale.new(glotpress: 'gl', android: 'gl'), + Locale.new(glotpress: 'is', android: 'is'), + Locale.new(glotpress: 'es-co', android: 'es-rCO'), + Locale.new(glotpress: 'kmr', android: 'kmr'), ].freeze MAG16_GP_CODES = %w[ar de es fr he id it ja ko nl pt-br ru sv tr zh-cn zh-tw].freeze @@ -72,7 +71,6 @@ class Locales ## Static Methods class << self - # @return [Array<Locale>] Array of all the known locales # def all @@ -117,6 +115,7 @@ def search(key, code_or_list) code_or_list.map { |code| search(key, code) } else # String raise 'The locale code should not contain spaces. Did you accidentally use `%[]` instead of `%w[]` at call site?' if code_or_list.include?(' ') + ALL_KNOWN_LOCALES.find { |locale| locale.send(key) == code_or_list } || not_found(code_or_list, key) end end diff --git a/spec/locales_spec.rb b/spec/locales_spec.rb index 84a32cac4..e5576b0d1 100644 --- a/spec/locales_spec.rb +++ b/spec/locales_spec.rb @@ -8,9 +8,9 @@ end it 'raises if no locale was found for a given code' do - expect { + expect do Fastlane::Locale['invalidcode'] - }.to raise_error(RuntimeError, "Unknown locale for glotpress code 'invalidcode'") + end.to raise_error(RuntimeError, "Unknown locale for glotpress code 'invalidcode'") end end @@ -37,9 +37,9 @@ end it 'raises if one of the locale codes passed was not found' do - expect { + expect do Fastlane::Locales.send(method_sym, [fr_code, 'invalidcode', 'pt-br']) - }.to raise_error(RuntimeError, "Unknown locale for #{key} code 'invalidcode'") + end.to raise_error(RuntimeError, "Unknown locale for #{key} code 'invalidcode'") end end @@ -95,7 +95,7 @@ mag16_except_pt = Fastlane::Locales.mag16 - Fastlane::Locales['pt-br'] expect(mag16_except_pt.count).to equal(15) expect(mag16_except_pt.find { |l| l.glotpress == 'pt-br' }).to be_nil - expect(mag16_except_pt.find { |l| l.glotpress == 'fr' }).to_not be_nil + expect(mag16_except_pt.find { |l| l.glotpress == 'fr' }).not_to be_nil end it 'can convert a Locale to a hash' do From 6a883ad6e5c1d06890064b03be58569225c7058a Mon Sep 17 00:00:00 2001 From: Olivier Halligon <olivier.halligon@automattic.com> Date: Tue, 10 Aug 2021 19:26:17 +0200 Subject: [PATCH 03/10] Split specs in 2 files + use described_class --- .rubocop_todo.yml | 2 ++ spec/locale_spec.rb | 20 ++++++++++++++++++++ spec/locales_spec.rb | 35 ++++++++--------------------------- 3 files changed, 30 insertions(+), 27 deletions(-) create mode 100644 spec/locale_spec.rb diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 677efef55..6d6b32fc0 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -142,6 +142,8 @@ RSpec/FilePath: - 'spec/ios_merge_translators_strings_spec.rb' - 'spec/release_notes_helper_spec.rb' - 'spec/check_localization_progress_spec.rb' + - 'spec/locale_spec.rb' + - 'spec/locales_spec.rb' # Offense count: 8 # Cop supports --auto-correct. diff --git a/spec/locale_spec.rb b/spec/locale_spec.rb new file mode 100644 index 000000000..f2bac484c --- /dev/null +++ b/spec/locale_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' + +describe Fastlane::Locale do + it 'returns a single Locale if one was found' do + locale = described_class['fr'] + expect(locale).to be_instance_of(described_class) + expect(locale.glotpress).to eq('fr') + end + + it 'raises if no locale was found for a given code' do + expect do + described_class['invalidcode'] + end.to raise_error(RuntimeError, "Unknown locale for glotpress code 'invalidcode'") + end + + it 'can convert a Locale to a hash' do + h = described_class['fr'].to_h + expect(h).to eq({ glotpress: 'fr', android: 'fr', google_play: 'fr-FR', ios: nil, app_store: nil }) + end +end diff --git a/spec/locales_spec.rb b/spec/locales_spec.rb index e5576b0d1..435cd1153 100644 --- a/spec/locales_spec.rb +++ b/spec/locales_spec.rb @@ -1,24 +1,10 @@ require 'spec_helper' -describe Fastlane::Locale do - it 'returns a single Locale if one was found' do - locale = Fastlane::Locale['fr'] - expect(locale).to be_instance_of(Fastlane::Locale) - expect(locale.glotpress).to eq('fr') - end - - it 'raises if no locale was found for a given code' do - expect do - Fastlane::Locale['invalidcode'] - end.to raise_error(RuntimeError, "Unknown locale for glotpress code 'invalidcode'") - end -end - describe Fastlane::Locales do shared_examples 'from_xxx' do |key, fr_code, pt_code| let(:method_sym) { "from_#{key}".to_sym } it 'can find a locale from a single code' do - fr_locale = Fastlane::Locales.send(method_sym, fr_code) + fr_locale = described_class.send(method_sym, fr_code) expect(fr_locale).to be_instance_of(Fastlane::Locale) expect(fr_locale.glotpress).to eq('fr') expect(fr_locale.android).to eq('fr') @@ -26,7 +12,7 @@ end it 'can find locales from a multiple codes' do - locales = Fastlane::Locales.send(method_sym, [fr_code, pt_code]) + locales = described_class.send(method_sym, [fr_code, pt_code]) expect(locales).to be_instance_of(Array) expect(locales[0]).to be_instance_of(Fastlane::Locale) @@ -38,7 +24,7 @@ it 'raises if one of the locale codes passed was not found' do expect do - Fastlane::Locales.send(method_sym, [fr_code, 'invalidcode', 'pt-br']) + described_class.send(method_sym, [fr_code, 'invalidcode', 'pt-br']) end.to raise_error(RuntimeError, "Unknown locale for #{key} code 'invalidcode'") end end @@ -59,14 +45,14 @@ describe 'subscript [] operator' do it 'returns an Array<Locale> even if a single one was passed' do - locales = Fastlane::Locales['fr'] + locales = described_class['fr'] expect(locales).to be_instance_of(Array) expect(locales.count).to equal(1) expect(locales[0].glotpress).to eq('fr') end it 'returns an Array<Locale> if a list of vararg codes was passed' do - locales = Fastlane::Locales['fr', 'pt-br'] + locales = described_class['fr', 'pt-br'] expect(locales).to be_instance_of(Array) expect(locales.count).to equal(2) expect(locales[0]).to be_instance_of(Fastlane::Locale) @@ -77,7 +63,7 @@ it 'returns an Array<Locale> if an Array<String> of codes was passed' do list = %w[fr pt-br] - locales = Fastlane::Locales[list] + locales = described_class[list] expect(locales).to be_instance_of(Array) expect(locales.count).to equal(2) expect(locales[0]).to be_instance_of(Fastlane::Locale) @@ -88,18 +74,13 @@ end it 'returns exactly 16 Mag16 locales' do - expect(Fastlane::Locales.mag16.count).to eq(16) + expect(described_class.mag16.count).to eq(16) end it 'is easy to do Locale subset intersections' do - mag16_except_pt = Fastlane::Locales.mag16 - Fastlane::Locales['pt-br'] + mag16_except_pt = described_class.mag16 - described_class['pt-br'] expect(mag16_except_pt.count).to equal(15) expect(mag16_except_pt.find { |l| l.glotpress == 'pt-br' }).to be_nil expect(mag16_except_pt.find { |l| l.glotpress == 'fr' }).not_to be_nil end - - it 'can convert a Locale to a hash' do - h = Fastlane::Locale['fr'].to_h - expect(h).to eq({ glotpress: 'fr', android: 'fr', google_play: 'fr-FR', ios: nil, app_store: nil }) - end end From b67733a9a402d40e675dfdee73e3cbc5dff85813 Mon Sep 17 00:00:00 2001 From: Olivier Halligon <olivier.halligon@automattic.com> Date: Tue, 10 Aug 2021 19:46:31 +0200 Subject: [PATCH 04/10] Improve YARD documention --- .../wpmreleasetoolkit/models/locales.rb | 37 ++++++++++++++----- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb b/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb index 4588c160f..1175af66a 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb @@ -1,10 +1,19 @@ module Fastlane + # Define a single Locale with the various locale codes depending on the representation needed Locale = Struct.new(:glotpress, :android, :google_play, :ios, :app_store, keyword_init: true) do + # Returns the Locale with the given glotpress locale code from the list of all known locales (`Locales.all`) + # + # @param [String] The glotpress locale code for the locale to fetch + # @return [Locale] The locale found + # @raise [RuntimeException] if the locale with given glotpress code is unknown def self.[](code) Locales[code].first end end + # A class with static methods to manipulate lists of locales. + # Exposes various `Array<Locale>` lists like all known locales, the Mag16, + # and convenience methods to turn list of Strings into list of Locales. class Locales ################### ## Constants @@ -77,28 +86,36 @@ def all ALL_KNOWN_LOCALES end - # Define from_glotpress(code_or_list), from_android(code_or_list) … methods + # Define from_glotpress(code_or_list), from_android(code_or_list) … methods. + # + # Those can be used in the rare cases where you need to find locales via codes other than the glotpress ones, + # like searching by android locale code(s) or google_play locale code(s). + # In most cases, prefer using the `Locales[…]` method instead ()with glotpress locale codes). # # @param [Array<String>, String] list of locale codes to search for, or single value for single result - # @return [Array<Locale>, Locale] list of found locales (empty if none found), or single locale if a single value was passed (or nil if not found) + # @return [Array<Locale>, Locale] list of found locales, or single locale if a single value was passed + # @raise [RuntimeException] if at least one of the locale codes was unknown # %i[glotpress android google_play ios app_store].each do |key| - define_method("from_#{key}") { |args| search(key, args) } + define_method("from_#{key}") { |args| search!(key, args) } end # Return an Array<Locale> based on glotpress locale codes # - # @note If you need a single locale, you can use Locale[code] instead of Locales[code] + # @note If you need a single locale instead of an `Array<Locale>`, you can use Locale[code] instead of Locales[code] + # # @param [String..., Array<String>] Arbitrary list of strings, either passed as a single array parameter, or as a vararg list of params # @return [Array<Locale>] The found locales. + # @raise [RuntimeException] if at least one of the locale codes was unknown # def [](*list) - # If we passed an Array, `*list` will make it an Array<Array<String>>, so taking `list.first` in those cases to go back to Array<String> + # If we passed a variadic list of Strings, `*list` will make it a single `Array<String>` and we were already good to go. + # But if we passed an Array, `*list` will make it an Array<Array<String>> of one item; taking `list.first` will go back to Array<String>. list = list.first if list.count == 1 && list.first.is_a?(Array) from_glotpress(list) end - # Return the subset of the 16 locales most of our apps are localized 100% (what we call the "Magnificent 16") + # Return the subset of the 16 locales most of our apps are localized 100% (the ones we call the "Magnificent 16") # # @return [Array<Locale>] List of the Mag16 locales def mag16 @@ -110,17 +127,17 @@ def mag16 private # Search the known locales for just the ones having the provided locale code, where the codes are expressed using the standard for the given key - def search(key, code_or_list) + def search!(key, code_or_list) if code_or_list.is_a?(Array) - code_or_list.map { |code| search(key, code) } + code_or_list.map { |code| search!(key, code) } else # String raise 'The locale code should not contain spaces. Did you accidentally use `%[]` instead of `%w[]` at call site?' if code_or_list.include?(' ') - ALL_KNOWN_LOCALES.find { |locale| locale.send(key) == code_or_list } || not_found(code_or_list, key) + ALL_KNOWN_LOCALES.find { |locale| locale.send(key) == code_or_list } || not_found!(code_or_list, key) end end - def not_found(code, key) + def not_found!(code, key) raise "Unknown locale for #{key} code '#{code}'" end end From fdb429f260773e326b6d1638d8fdfa1029323b05 Mon Sep 17 00:00:00 2001 From: Olivier Halligon <olivier.halligon@automattic.com> Date: Tue, 10 Aug 2021 20:10:17 +0200 Subject: [PATCH 05/10] Introduce a couple of ios/app_store values for some Locales as a starting point + enable missing corresponding specs --- lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb | 8 ++++---- spec/locale_spec.rb | 2 +- spec/locales_spec.rb | 9 ++++++++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb b/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb index 1175af66a..e82956c40 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb @@ -23,7 +23,7 @@ class Locales Locale.new(glotpress: 'en-gb', android: 'en-rGB', google_play: 'en-US'), Locale.new(glotpress: 'es', android: 'es', google_play: 'es-ES'), Locale.new(glotpress: 'fr-ca', android: 'fr-rCA', google_play: 'fr-CA'), - Locale.new(glotpress: 'fr', android: 'fr', google_play: 'fr-FR'), + Locale.new(glotpress: 'fr', android: 'fr', google_play: 'fr-FR', ios: 'fr-FR', app_store: 'fr-FR'), Locale.new(glotpress: 'he', android: 'he', google_play: 'iw-IL'), Locale.new(glotpress: 'id', android: 'id', google_play: 'id'), Locale.new(glotpress: 'it', android: 'it', google_play: 'it-IT'), @@ -31,15 +31,15 @@ class Locales Locale.new(glotpress: 'ko', android: 'ko', google_play: 'ko-KR'), Locale.new(glotpress: 'nl', android: 'nl', google_play: 'nl-NL'), Locale.new(glotpress: 'pl', android: 'pl', google_play: 'pl-PL'), - Locale.new(glotpress: 'pt-br', android: 'pt-rBR', google_play: 'pt-BR'), + Locale.new(glotpress: 'pt-br', android: 'pt-rBR', google_play: 'pt-BR', ios: 'pt-BR', app_store: 'pt-BR'), Locale.new(glotpress: 'ru', android: 'ru', google_play: 'ru-RU'), Locale.new(glotpress: 'sr', android: 'sr', google_play: 'sr'), Locale.new(glotpress: 'sv', android: 'sv', google_play: 'sv-SE'), Locale.new(glotpress: 'th', android: 'th', google_play: 'th'), Locale.new(glotpress: 'tr', android: 'tr', google_play: 'tr-TR'), Locale.new(glotpress: 'vi', android: 'vi', google_play: 'vi'), - Locale.new(glotpress: 'zh-cn', android: 'zh-rCN', google_play: 'zh-CN'), - Locale.new(glotpress: 'zh-tw', android: 'zh-rTW', google_play: 'zh-TW'), + Locale.new(glotpress: 'zh-cn', android: 'zh-rCN', google_play: 'zh-CN', ios: 'zh-Hans', app_store: 'zh-Hans'), + Locale.new(glotpress: 'zh-tw', android: 'zh-rTW', google_play: 'zh-TW', ios: 'zh-Hant', app_store: 'zh-Hant'), Locale.new(glotpress: 'az', android: 'az'), Locale.new(glotpress: 'el', android: 'el'), Locale.new(glotpress: 'es-mx', android: 'es-rMX'), diff --git a/spec/locale_spec.rb b/spec/locale_spec.rb index f2bac484c..d22ba63bd 100644 --- a/spec/locale_spec.rb +++ b/spec/locale_spec.rb @@ -15,6 +15,6 @@ it 'can convert a Locale to a hash' do h = described_class['fr'].to_h - expect(h).to eq({ glotpress: 'fr', android: 'fr', google_play: 'fr-FR', ios: nil, app_store: nil }) + expect(h).to eq({ glotpress: 'fr', android: 'fr', google_play: 'fr-FR', ios: 'fr-FR', app_store: 'fr-FR' }) end end diff --git a/spec/locales_spec.rb b/spec/locales_spec.rb index 435cd1153..c88da05da 100644 --- a/spec/locales_spec.rb +++ b/spec/locales_spec.rb @@ -3,6 +3,7 @@ describe Fastlane::Locales do shared_examples 'from_xxx' do |key, fr_code, pt_code| let(:method_sym) { "from_#{key}".to_sym } + it 'can find a locale from a single code' do fr_locale = described_class.send(method_sym, fr_code) expect(fr_locale).to be_instance_of(Fastlane::Locale) @@ -41,7 +42,13 @@ include_examples 'from_xxx', :google_play, 'fr-FR', 'pt-BR' end - # @TODO: from_ios, from_app_store + describe 'from_ios' do + include_examples 'from_xxx', :ios, 'fr-FR', 'pt-BR' + end + + describe 'from_app_store' do + include_examples 'from_xxx', :app_store, 'fr-FR', 'pt-BR' + end describe 'subscript [] operator' do it 'returns an Array<Locale> even if a single one was passed' do From 7a15db8d15fe0284bb633da416510dc7c93be1ed Mon Sep 17 00:00:00 2001 From: Olivier Halligon <olivier.halligon@automattic.com> Date: Tue, 10 Aug 2021 20:13:34 +0200 Subject: [PATCH 06/10] Add a spec to test locale code formats are consistent --- spec/locales_spec.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/spec/locales_spec.rb b/spec/locales_spec.rb index c88da05da..0de4a87ca 100644 --- a/spec/locales_spec.rb +++ b/spec/locales_spec.rb @@ -80,6 +80,16 @@ end end + it 'has only valid codes for known locales' do + described_class.all.each do |locale| + expect(locale.glotpress || 'xx').to match(/^[a-z]{2,3}(-[a-z]{2})?$/) + expect(locale.android || 'xx-rYY').to match(/^[a-z]{2,3}(-r[A-Z]{2})?$/) + expect(locale.google_play || 'xx-YY').to match(/^[a-z]{2,3}(-[A-Z]{2})?$/) + expect(locale.app_store || 'xx-Yy').to match(/^[a-z]{2,3}(-[A-Za-z]{2,4})?$/) + expect(locale.ios || 'xx-Yy').to match(/^[a-z]{2,3}(-[A-Za-z]{2,4})?$/) + end + end + it 'returns exactly 16 Mag16 locales' do expect(described_class.mag16.count).to eq(16) end From 58188a5cb878a650de2c15186b211936e5c894e8 Mon Sep 17 00:00:00 2001 From: Olivier Halligon <olivier.halligon@automattic.com> Date: Fri, 13 Aug 2021 18:21:31 +0200 Subject: [PATCH 07/10] typos --- lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb | 2 +- spec/locales_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb b/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb index e82956c40..158b9d8fb 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb @@ -90,7 +90,7 @@ def all # # Those can be used in the rare cases where you need to find locales via codes other than the glotpress ones, # like searching by android locale code(s) or google_play locale code(s). - # In most cases, prefer using the `Locales[…]` method instead ()with glotpress locale codes). + # In most cases, prefer using the `Locales[…]` method instead (with glotpress locale codes). # # @param [Array<String>, String] list of locale codes to search for, or single value for single result # @return [Array<Locale>, Locale] list of found locales, or single locale if a single value was passed diff --git a/spec/locales_spec.rb b/spec/locales_spec.rb index 0de4a87ca..6b1dd9823 100644 --- a/spec/locales_spec.rb +++ b/spec/locales_spec.rb @@ -25,7 +25,7 @@ it 'raises if one of the locale codes passed was not found' do expect do - described_class.send(method_sym, [fr_code, 'invalidcode', 'pt-br']) + described_class.send(method_sym, [fr_code, 'invalidcode', pt_code]) end.to raise_error(RuntimeError, "Unknown locale for #{key} code 'invalidcode'") end end From 5e80651f67f1ad36014cd302dd87e11ad0cdfc75 Mon Sep 17 00:00:00 2001 From: Olivier Halligon <olivier.halligon@automattic.com> Date: Thu, 16 Sep 2021 22:05:14 +0200 Subject: [PATCH 08/10] Fix git failures in rspecs When run with a modern git version which supports `--initial-branch`, git init was run twice due to using `|` instead of expected `||` in the shell commands --- spec/configure_helper_spec.rb | 2 +- spec/git_helper_spec.rb | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/spec/configure_helper_spec.rb b/spec/configure_helper_spec.rb index c45833f1f..00931f77b 100644 --- a/spec/configure_helper_spec.rb +++ b/spec/configure_helper_spec.rb @@ -16,7 +16,7 @@ # reasonable enough assumption to make for the real world usage of this # tool. Still, it would be nice to have proper handling of that # scenario at some point. - `git init --initial-branch main | git init` + `git init --initial-branch main || git init` expect(Fastlane::UI).to receive(:user_error!) diff --git a/spec/git_helper_spec.rb b/spec/git_helper_spec.rb index 4d8edf8a6..1b5ece305 100644 --- a/spec/git_helper_spec.rb +++ b/spec/git_helper_spec.rb @@ -26,12 +26,12 @@ end it 'can detect a valid git repository' do - `git init --initial-branch main | git init` + `git init --initial-branch main || git init` expect(Fastlane::Helper::GitHelper.is_git_repo?).to be true end it 'can detect a valid git repository from a child folder' do - `git init --initial-branch main | git init` + `git init --initial-branch main || git init` `mkdir -p a/b` Dir.chdir('./a/b') expect(Fastlane::Helper::GitHelper.is_git_repo?).to be true @@ -39,14 +39,14 @@ it 'can detect a valid git repository when given a path' do Dir.mktmpdir do |dir| - `git -C #{dir} init --initial-branch main | git -C #{dir} init` + `git -C #{dir} init --initial-branch main || git -C #{dir} init` expect(Fastlane::Helper::GitHelper.is_git_repo?(path: dir)).to be true end end it 'can detect a valid git repository when given a child folder path' do Dir.mktmpdir do |dir| - `git -C #{dir} init --initial-branch main | git -C #{dir} init` + `git -C #{dir} init --initial-branch main || git -C #{dir} init` path = File.join(dir, 'a', 'b') `mkdir -p #{path}` expect(Fastlane::Helper::GitHelper.is_git_repo?(path: path)).to be true @@ -54,13 +54,13 @@ end it 'can detect a repository with Git-lfs enabled' do - `git init --initial-branch main | git init` + `git init --initial-branch main || git init` `git lfs install` expect(Fastlane::Helper::GitHelper.has_git_lfs?).to be true end it 'can detect a repository without Git-lfs enabled' do - `git init --initial-branch main | git init` + `git init --initial-branch main || git init` `git lfs uninstall &>/dev/null` expect(Fastlane::Helper::GitHelper.is_git_repo?).to be true expect(Fastlane::Helper::GitHelper.has_git_lfs?).to be false @@ -186,7 +186,7 @@ end def setup_git_repo(dummy_file_path: nil, add_file_to_gitignore: false, commit_gitignore: false) - `git init --initial-branch main | git init` + `git init --initial-branch main || git init` `touch .gitignore` `git add .gitignore && git commit -m 'Add .gitignore'` From 682acd66d9f053e27c1c5419187b11a3d0e1d1d6 Mon Sep 17 00:00:00 2001 From: Olivier Halligon <olivier.halligon@automattic.com> Date: Thu, 16 Sep 2021 22:06:54 +0200 Subject: [PATCH 09/10] Detailed YARD documentation about the various Locale code standards used for each key/context + Split locale.rb and locales.rb --- .../plugin/wpmreleasetoolkit/models/locale.rb | 40 +++++++++++++++++++ .../wpmreleasetoolkit/models/locales.rb | 16 ++------ 2 files changed, 44 insertions(+), 12 deletions(-) create mode 100644 lib/fastlane/plugin/wpmreleasetoolkit/models/locale.rb diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/models/locale.rb b/lib/fastlane/plugin/wpmreleasetoolkit/models/locale.rb new file mode 100644 index 000000000..0e37dbc62 --- /dev/null +++ b/lib/fastlane/plugin/wpmreleasetoolkit/models/locale.rb @@ -0,0 +1,40 @@ +module Fastlane + # Defines a single Locale with the various locale codes depending on the representation needed. + # + # The various locale codes formats for the various keys can be found as follows: + # + # - glotpress: + # Go to the GP project page (e.g. https://translate.wordpress.org/projects/apps/android/dev/) + # and hover over the link for each locale, locale code is in the URL. + # - android: (`values-*` folder names) + # See https://developer.android.com/guide/topics/resources/providing-resources#AlternativeResources (Scroll to Table 2) + # [ISO639-1 (lowercase)]-r[ISO-3166-alpha-2 (uppercase)], e.g. `zh-rCN` ("Chinese understood in mainland China") + # - google_play: (PlayStore Console, for metadata, release_notes.xml and `fastlane supply`) + # See https://support.google.com/googleplay/android-developer/answer/9844778 (then open "View list of available languages"). + # See also https://github.com/fastlane/fastlane/blob/master/supply/lib/supply/languages.rb + # - ios: (`*.lproj`) + # See https://developer.apple.com/documentation/xcode/choosing-localization-regions-and-scripts#Understand-the-Language-Identifier + # [ISO639-1/ISO639-2 (lowercase)]-[ISO 3166-1 (uppercase region or titlecase script)], e.g. `zh-Hans` ("Simplified Chinese" script) + # - app_store: (AppStoreConnect, for metadata and `fastlane deliver`) + # See https://github.com/fastlane/fastlane/blob/master/deliver/lib/deliver/languages.rb + # + # Links to ISO Standards + # ISO standard portal: https://www.iso.org/obp/ui/#search + # ISO 639-1: https://www.loc.gov/standards/iso639-2/php/code_list.php + # ISO-3166-alpha2: https://www.iso.org/obp/ui/#iso:pub:PUB500001:en + # + # Notes about region vs script codes in ISO-3166-1 + # `zh-CN` is a locale code - Chinese understood in mainland China + # `zh-Hans` is a language+script code - Chinese written in Simplified Chinese (not just understood in mainland China) + # + Locale = Struct.new(:glotpress, :android, :google_play, :ios, :app_store, keyword_init: true) do + # Returns the Locale with the given glotpress locale code from the list of all known locales (`Locales.all`) + # + # @param [String] The glotpress locale code for the locale to fetch + # @return [Locale] The locale found + # @raise [RuntimeException] if the locale with given glotpress code is unknown + def self.[](code) + Locales[code].first + end + end +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb b/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb index 158b9d8fb..f62a373de 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb @@ -1,19 +1,11 @@ -module Fastlane - # Define a single Locale with the various locale codes depending on the representation needed - Locale = Struct.new(:glotpress, :android, :google_play, :ios, :app_store, keyword_init: true) do - # Returns the Locale with the given glotpress locale code from the list of all known locales (`Locales.all`) - # - # @param [String] The glotpress locale code for the locale to fetch - # @return [Locale] The locale found - # @raise [RuntimeException] if the locale with given glotpress code is unknown - def self.[](code) - Locales[code].first - end - end +require_relative 'locale' +module Fastlane # A class with static methods to manipulate lists of locales. + # # Exposes various `Array<Locale>` lists like all known locales, the Mag16, # and convenience methods to turn list of Strings into list of Locales. + # class Locales ################### ## Constants From 8204b59a443bebe49042d4fda3bb98ae85fb9061 Mon Sep 17 00:00:00 2001 From: Olivier Halligon <olivier.halligon@automattic.com> Date: Thu, 16 Sep 2021 22:08:23 +0200 Subject: [PATCH 10/10] Rename from_xxx methods with a bang `!` Per ruby conventions, as they might raise on invalid/unknown values --- .../plugin/wpmreleasetoolkit/models/locales.rb | 6 +++--- spec/locales_spec.rb | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb b/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb index f62a373de..0cc6ee762 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/models/locales.rb @@ -89,7 +89,7 @@ def all # @raise [RuntimeException] if at least one of the locale codes was unknown # %i[glotpress android google_play ios app_store].each do |key| - define_method("from_#{key}") { |args| search!(key, args) } + define_method("from_#{key}!") { |args| search!(key, args) } end # Return an Array<Locale> based on glotpress locale codes @@ -104,14 +104,14 @@ def [](*list) # If we passed a variadic list of Strings, `*list` will make it a single `Array<String>` and we were already good to go. # But if we passed an Array, `*list` will make it an Array<Array<String>> of one item; taking `list.first` will go back to Array<String>. list = list.first if list.count == 1 && list.first.is_a?(Array) - from_glotpress(list) + from_glotpress!(list) end # Return the subset of the 16 locales most of our apps are localized 100% (the ones we call the "Magnificent 16") # # @return [Array<Locale>] List of the Mag16 locales def mag16 - from_glotpress(MAG16_GP_CODES) + from_glotpress!(MAG16_GP_CODES) end ################### diff --git a/spec/locales_spec.rb b/spec/locales_spec.rb index 6b1dd9823..269a1e9b0 100644 --- a/spec/locales_spec.rb +++ b/spec/locales_spec.rb @@ -2,7 +2,7 @@ describe Fastlane::Locales do shared_examples 'from_xxx' do |key, fr_code, pt_code| - let(:method_sym) { "from_#{key}".to_sym } + let(:method_sym) { "from_#{key}!".to_sym } it 'can find a locale from a single code' do fr_locale = described_class.send(method_sym, fr_code) @@ -30,23 +30,23 @@ end end - describe 'from_glotpress' do + describe 'from_glotpress!' do include_examples 'from_xxx', :glotpress, 'fr', 'pt-br' end - describe 'from_android' do + describe 'from_android!' do include_examples 'from_xxx', :android, 'fr', 'pt-rBR' end - describe 'from_google_play' do + describe 'from_google_play!' do include_examples 'from_xxx', :google_play, 'fr-FR', 'pt-BR' end - describe 'from_ios' do + describe 'from_ios!' do include_examples 'from_xxx', :ios, 'fr-FR', 'pt-BR' end - describe 'from_app_store' do + describe 'from_app_store!' do include_examples 'from_xxx', :app_store, 'fr-FR', 'pt-BR' end