1# frozen_string_literal: true 2 3require "gettext_i18n_rails/tasks" 4 5namespace :gettext do 6 task :compile do 7 # See: https://gitlab.com/gitlab-org/gitlab-foss/issues/33014#note_31218998 8 FileUtils.touch(pot_file_path) 9 10 Rake::Task['gettext:po_to_json'].invoke 11 end 12 13 desc 'Regenerate gitlab.pot file' 14 task :regenerate do 15 ensure_locale_folder_presence! 16 17 # Clean up folders that do not contain a gitlab.po file 18 Pathname.new(locale_path).children.each do |child| 19 next unless child.directory? 20 21 folder_path = child.to_path 22 23 if File.exist?("#{folder_path}/gitlab.po") 24 # remove all translated files to speed up finding 25 FileUtils.rm Dir["#{folder_path}/gitlab.*"] 26 else 27 # remove empty translation folders so we don't generate un-needed .po files 28 puts "Deleting #{folder_path} as it does not contain a 'gitlab.po' file." 29 30 FileUtils.rm_r folder_path 31 end 32 end 33 34 # remove the `pot` file to ensure it's completely regenerated 35 FileUtils.rm_f(pot_file_path) 36 37 Rake::Task['gettext:find'].invoke 38 39 # leave only the required changes. 40 unless system(*%w(git -c core.hooksPath=/dev/null checkout -- locale/*/gitlab.po)) 41 raise 'failed to cleanup generated locale/*/gitlab.po files' 42 end 43 44 raise 'gitlab.pot file not generated' unless File.exist?(pot_file_path) 45 46 # Remove timestamps from the pot file 47 pot_content = File.read pot_file_path 48 pot_content.gsub!(/^"POT?\-(?:Creation|Revision)\-Date\:.*\n/, '') 49 File.write pot_file_path, pot_content 50 51 puts <<~MSG 52 All done. Please commit the changes to `locale/gitlab.pot`. 53 54 MSG 55 end 56 57 desc 'Lint all po files in `locale/' 58 task lint: :environment do 59 require 'simple_po_parser' 60 require 'gitlab/utils' 61 require 'parallel' 62 63 FastGettext.silence_errors 64 files = Dir.glob(Rails.root.join('locale/*/gitlab.po')) 65 66 linters = files.map do |file| 67 locale = File.basename(File.dirname(file)) 68 69 Gitlab::I18n::PoLinter.new(po_path: file, locale: locale) 70 end 71 72 linters.unshift(Gitlab::I18n::PoLinter.new(po_path: pot_file_path)) 73 74 failed_linters = Parallel 75 .map(linters, progress: 'Linting po files') { |linter| linter if linter.errors.any? } 76 .compact 77 78 if failed_linters.empty? 79 puts 'All PO files are valid.' 80 else 81 failed_linters.each do |linter| 82 report_errors_for_file(linter.po_path, linter.errors) 83 end 84 85 raise "Not all PO-files are valid: #{failed_linters.map(&:po_path).to_sentence}" 86 end 87 end 88 89 task :updated_check do 90 # Removing all pre-translated files speeds up `gettext:find` as the 91 # files don't need to be merged. 92 # Having `LC_MESSAGES/gitlab.mo files present also confuses the output. 93 FileUtils.rm Dir['locale/**/gitlab.*'] 94 FileUtils.rm_f pot_file_path 95 96 # `gettext:find` writes touches to temp files to `stderr` which would cause 97 # `static-analysis` to report failures. We can ignore these. 98 silence_stderr do 99 Rake::Task['gettext:find'].invoke 100 end 101 102 pot_diff = `git diff -- #{pot_file_path} | grep -E '^(\\+|-)msgid'`.strip 103 104 # reset the locale folder for potential next tasks 105 `git checkout -- locale` 106 107 if pot_diff.present? 108 raise <<~MSG 109 Changes in translated strings found, please update file `#{pot_file_path}` by running: 110 111 bin/rake gettext:regenerate 112 113 Then commit and push the resulting changes to `#{pot_file_path}`. 114 115 The diff was: 116 117 #{pot_diff} 118 MSG 119 end 120 end 121 122 private 123 124 # Customize list of translatable files 125 # See: https://github.com/grosser/gettext_i18n_rails#customizing-list-of-translatable-files 126 def files_to_translate 127 folders = %W(ee app lib config #{locale_path}).join(',') 128 exts = %w(rb erb haml slim rhtml js jsx vue handlebars hbs mustache).join(',') 129 130 Dir.glob( 131 "{#{folders}}/**/*.{#{exts}}" 132 ) 133 end 134 135 def report_errors_for_file(file, errors_for_file) 136 puts "Errors in `#{file}`:" 137 138 errors_for_file.each do |message_id, errors| 139 puts " #{message_id}" 140 errors.each do |error| 141 spaces = ' ' * 4 142 error = error.lines.join("#{spaces}") 143 puts "#{spaces}#{error}" 144 end 145 end 146 end 147 148 def silence_stderr(&block) 149 old_stderr = $stderr.dup 150 $stderr.reopen(File::NULL) 151 $stderr.sync = true 152 153 yield 154 ensure 155 $stderr.reopen(old_stderr) 156 old_stderr.close 157 end 158 159 def ensure_locale_folder_presence! 160 unless Dir.exist?(locale_path) 161 raise <<~MSG 162 Cannot find '#{locale_path}' folder. Please ensure you're running this task from the gitlab repo. 163 164 MSG 165 end 166 end 167 168 def locale_path 169 @locale_path ||= Rails.root.join('locale') 170 end 171 172 def pot_file_path 173 @pot_file_path ||= File.join(locale_path, 'gitlab.pot') 174 end 175end 176