Module: I18nScrewdriver

Defined in:
lib/i18n_screwdriver.rb,
lib/i18n_screwdriver/version.rb,
lib/i18n_screwdriver/translation.rb,
lib/i18n_screwdriver/rails/engine.rb,
lib/i18n_screwdriver/translation_helper.rb

Defined Under Namespace

Modules: Rails, TranslationHelper Classes: Translation

Constant Summary collapse

Error =
Class.new(StandardError)
VERSION =
"12.0.0"

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.excluded_pathsObject

Returns the value of attribute excluded_paths.



10
11
12
# File 'lib/i18n_screwdriver.rb', line 10

def excluded_paths
  @excluded_paths
end

.included_gemsObject

Returns the value of attribute included_gems.



10
11
12
# File 'lib/i18n_screwdriver.rb', line 10

def included_gems
  @included_gems
end

Class Method Details

.available_localesObject



153
154
155
156
157
158
# File 'lib/i18n_screwdriver.rb', line 153

def self.available_locales
  @available_locales ||= begin
    raise Error, "Please set I18.available_locales" unless I18n.available_locales.count > 0
    I18n.available_locales.map(&:to_s)
  end
end

.default_localeObject



146
147
148
149
150
151
# File 'lib/i18n_screwdriver.rb', line 146

def self.default_locale
  @default_locale ||= begin
    raise Error, "Please set I18.default_locale" unless I18n.default_locale.present?
    I18n.default_locale.to_s
  end
end

.excluded_path?(path) ⇒ Boolean

Returns:

  • (Boolean)


103
104
105
# File 'lib/i18n_screwdriver.rb', line 103

def self.excluded_path?(path)
  excluded_paths.detect{ |excluded_path| path =~ excluded_path }
end

.file_with_translations_exists?(locale) ⇒ Boolean

Returns:

  • (Boolean)


26
27
28
# File 'lib/i18n_screwdriver.rb', line 26

def self.file_with_translations_exists?(locale)
  File.exist?(filename_for_locale(locale))
end

.filename_for_locale(locale) ⇒ Object



16
17
18
# File 'lib/i18n_screwdriver.rb', line 16

def self.filename_for_locale(locale)
  File.join("config", "locales", "application.#{locale}.yml")
end

.gather_js_translations(path, texts) ⇒ Object



118
119
120
121
122
123
124
125
126
# File 'lib/i18n_screwdriver.rb', line 118

def self.gather_js_translations(path, texts)
  Dir.glob("#{path}/**/*.{js,jsx,ts,tsx,coffee,hamlc,ejs,erb}").each do |file|
    next unless File.file?(file)
    next if excluded_path?(file)
    puts "Scanning #{file}..."
    input = File.read(file)
    texts.concat(grab_js_texts_to_be_translated(input))
  end
end

.gather_ruby_translations(path, texts, symbols) ⇒ Object



107
108
109
110
111
112
113
114
115
116
# File 'lib/i18n_screwdriver.rb', line 107

def self.gather_ruby_translations(path, texts, symbols)
  Dir.glob("#{path}/**/*.{haml,erb,slim,rb}").each do |file|
    next unless File.file?(file)
    next if excluded_path?(file)
    puts "Scanning #{file}..."
    input = File.read(file)
    texts.concat(grab_texts_to_be_translated(input))
    symbols.concat(grab_symbols_to_be_translated(input))
  end
end

.gather_translationsObject



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/i18n_screwdriver.rb', line 128

def self.gather_translations
  texts = []
  symbols = []

  gather_ruby_translations(".", texts, symbols)
  gather_js_translations(".", texts)

  included_gems.each do |name|
    spec = Gem.loaded_specs[name]
    next puts "WARNING: gem #{name} not loaded, so it cannot be scanned for translations!" unless spec
    gather_ruby_translations(spec.full_gem_path, texts, symbols)
    gather_js_translations(spec.full_gem_path, texts)
  end

  translations = Hash[texts.uniq.map{ |text| [generate_key(text), text] }]
  translations.merge(Hash[symbols.uniq.map{ |symbol| [generate_key(symbol), ""] }])
end

.generate_key(source) ⇒ Object



20
21
22
23
24
# File 'lib/i18n_screwdriver.rb', line 20

def self.generate_key(source)
  return ":#{source}" if source.is_a?(Symbol)
  source = source.strip
  (source =~ /^:[a-z][a-z0-9_]*$/) ? source : Digest::MD5.hexdigest(source)
end

.grab_js_texts_to_be_translated(string) ⇒ Object



56
57
58
59
60
61
62
# File 'lib/i18n_screwdriver.rb', line 56

def self.grab_js_texts_to_be_translated(string)
  [].tap do |texts|
    texts.concat(string.scan(/\bI18n\.screw\w*\(?\s*(?<!\\)"(.*?)(?<!\\)"/).map{ |v| unescape_string(v[0]) })
    texts.concat(string.scan(/\bI18n\.screw\w*\(?\s*(?<!\\)'(.*?)(?<!\\)'/).map{ |v| unescape_string(v[0]) })
    texts.concat(string.scan(/\bI18n\.screw\w*\(?\s*(?<!\\)`(.*?)(?<!\\)`/).map{ |v| unescape_string(v[0]) })
  end
end

.grab_symbols_to_be_translated(string) ⇒ Object



52
53
54
# File 'lib/i18n_screwdriver.rb', line 52

def self.grab_symbols_to_be_translated(string)
  string.scan(/_\((:[a-z][a-z0-9_]*)\)/).flatten
end

.grab_texts_to_be_translated(string) ⇒ Object



45
46
47
48
49
50
# File 'lib/i18n_screwdriver.rb', line 45

def self.grab_texts_to_be_translated(string)
  [].tap do |texts|
    texts.concat(string.scan(/_\((?<!\\)"(.*?)(?<!\\)"/).map{ |v| unescape_string(v[0]) })
    texts.concat(string.scan(/_\((?<!\\)'(.*?)(?<!\\)'/).map{ |v| unescape_string(v[0]) })
  end
end

.in_utf8(hash) ⇒ Object



64
65
66
67
68
69
70
# File 'lib/i18n_screwdriver.rb', line 64

def self.in_utf8(hash)
  {}.tap do |result|
    hash.sort.each do |k, v|
      result[k.encode('UTF-8')] = (v || "").encode('UTF-8')
    end
  end
end

.load_translations(locale) ⇒ Object

Raises:



30
31
32
33
34
# File 'lib/i18n_screwdriver.rb', line 30

def self.load_translations(locale)
  path = filename_for_locale(locale)
  raise Error, "File #{path} not found!" unless File.exist?(path)
  sanitize_hash(YAML.load_file(path)[locale])
end

.sanitize_hash(hash) ⇒ Object



172
173
174
175
176
# File 'lib/i18n_screwdriver.rb', line 172

def self.sanitize_hash(hash)
  {}.tap do |new_hash|
    hash.each{ |k, v| new_hash[k.to_s] = v.to_s }
  end
end

.translate(string, **options) ⇒ Object



178
179
180
181
182
# File 'lib/i18n_screwdriver.rb', line 178

def self.translate(string, **options)
  I18n.translate!(generate_key(string), **options).split("|").last
rescue I18n::MissingTranslationData
  I18n.translate(string, **options)
end

.unescape_string(string) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/i18n_screwdriver.rb', line 72

def self.unescape_string(string)
  "".tap do |result|
    in_backslash = false
    string.each_char do |char|
      if in_backslash
        case char
        when 'r'
          result << "\r"
        when 'n'
          result << "\n"
        when 't'
          result << "\t"
        when '"', "'", '\\'
          result << char
        else
          result << '\\'
          result << char
        end
        in_backslash = false
      else
        case char
        when '\\'
          in_backslash = true
        else
          result << char
        end
      end
    end
  end
end

.update_translations_file(locale, translations) ⇒ Object



160
161
162
163
164
165
166
167
168
169
170
# File 'lib/i18n_screwdriver.rb', line 160

def self.update_translations_file(locale, translations)
  existing_translations = file_with_translations_exists?(locale) ? load_translations(locale) : {}
  existing_translations.select!{ |k| translations.has_key?(k) }

  translations.each do |k, v|
    next if existing_translations[k]
    existing_translations[k] = (default_locale == locale) ? v : nil
  end

  write_translations(locale, existing_translations)
end

.write_translations(locale, translations) ⇒ Object



36
37
38
39
40
41
42
43
# File 'lib/i18n_screwdriver.rb', line 36

def self.write_translations(locale, translations)
  File.open(filename_for_locale(locale), "w") do |file|
    file.puts "# use rake task i18n:update to generate this file"
    file.puts
    file.puts({locale => in_utf8(translations)}.to_yaml(:line_width => -1))
    file.puts
  end
end