Created
August 12, 2022 17:34
-
-
Save WaKeMaTTa/f854a210bec68a2f524d052f9dc28083 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'yaml' | |
if Gem::Version.new(Psych::LIBYAML_VERSION) < Gem::Version.new('0.2.5') | |
warn "Your libyaml library is outdated: please upgrade to >= 0.2.5.\n" \ | |
"The generated YAML will include output trailing spaces for empty scalar nodes, whereas " \ | |
"Phrase doesn't include them." | |
end | |
# Method to "deep sort" keys in a Hash (i.e. recursively), the way that Phrase would do. | |
# | |
# The "translation ordering on export" setting has been set to "Default" in Phrase. This is | |
# translated as MySQL `utf8mb4_general_ci` collation being used. (Whereas the "Natural" option | |
# is translated as `utf8mb4_unicode_ci` collation). | |
# | |
# This collation does not compare Strings exactly the same way as Ruby does. Especially, in this | |
# collation, the `_` character is considered to be **before** letters, whereas in Ruby it's | |
# considered as **after** (cf ASCII RFC https://www.rfc-editor.org/rfc/rfc20.html#page-2). | |
# | |
# in Ruby (and more generally in ASCII): | |
# | |
# '_' > 'a' => false | |
# | |
# in SQL: | |
# | |
# SELECT '_' > 'a' COLLATE utf8mb4_general_ci => 1 | |
# | |
# To mitigate this difference, we replace the `_` character by `|`, which is considered as before | |
# letters, in both Ruby and `utf8mb4_general_ci` MySQL collation (`'|' > 'a'` is true). | |
def sort_hash_alphabetically(hash) | |
hash.sort_by do |(key, _value)| | |
key.tr('_', '|') | |
end.to_h.transform_values! do |v| | |
v.is_a?(Hash) ? sort_hash_alphabetically(v) : v | |
end | |
end | |
APP_ROOT = File.expand_path('..', __dir__) | |
def locale_files | |
Dir.glob("#{APP_ROOT}/config/locales/**/*.yml") | |
end | |
def format_phrase(data) | |
YAML.dump(sort_hash_alphabetically(data)) | |
end | |
def check_the_format(fix: false) | |
error = false | |
locale_files.each do |filepath| | |
source = File.read(filepath) | |
formatted_source = format_phrase(YAML.load(source)) | |
if formatted_source != source | |
error = true | |
msg = fix ? 'is corrected' : 'not properly formatted' | |
puts "#{filepath.gsub(/^#{APP_ROOT}/, '.')} #{msg}" | |
end | |
File.write(filepath, formatted_source) if fix | |
end | |
if error | |
exit(1) | |
else | |
puts "Locale files are properly formatted" | |
exit | |
end | |
end | |
require 'optparse' | |
OptionParser.new do |opts| | |
opts.banner = "Usage: bin/format_phrase [options]" | |
opts.on("-f", "--fix", "Updates the locale files to Phrase format (default)") do | |
check_the_format(fix: true) | |
end | |
opts.on("-c", "--check", "Checks that locale files are properly formatted") do | |
check_the_format | |
end | |
opts.on("-h", "--help", "Prints this help") do | |
puts opts | |
exit | |
end | |
end.parse! | |
check_the_format(fix: true) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment