1. 16 9月, 2020 1 次提交
    • J
      Improve Action View `translate` helper · d81926fd
      Jonathan Hefner 提交于
      This disentangles the control flow between Action View's `translate` and
      I18n's `translate`.  In doing so, it fixes a handful of corner cases,
      for which tests have now been added.  It also reduces memory
      allocations, and improves speed when using a default:
      
      **Memory**
      
      ```ruby
      require "benchmark/memory"
      
      Benchmark.memory do |x|
        x.report("warmup") { translate(:"translations.foo"); translate(:"translations.html") }
        x.report("text") { translate(:"translations.foo") }
        x.report("html") { translate(:"translations.html") }
        x.report("text 1 default") { translate(:"translations.missing", default: :"translations.foo") }
        x.report("html 1 default") { translate(:"translations.missing", default: :"translations.html") }
        x.report("text 2 defaults") { translate(:"translations.missing", default: [:"translations.missing", :"translations.foo"]) }
        x.report("html 2 defaults") { translate(:"translations.missing", default: [:"translations.missing", :"translations.html"]) }
      end
      ```
      
      Before:
      
      ```
                      text     1.240k memsize (     0.000  retained)
                              13.000  objects (     0.000  retained)
                               2.000  strings (     0.000  retained)
                      html     1.600k memsize (     0.000  retained)
                              19.000  objects (     0.000  retained)
                               2.000  strings (     0.000  retained)
            text 1 default     4.728k memsize (     1.200k retained)
                              39.000  objects (     4.000  retained)
                               5.000  strings (     0.000  retained)
            html 1 default     5.056k memsize (     1.160k retained)
                              41.000  objects (     3.000  retained)
                               4.000  strings (     0.000  retained)
           text 2 defaults     7.464k memsize (     2.392k retained)
                              54.000  objects (     6.000  retained)
                               4.000  strings (     0.000  retained)
           html 2 defaults     7.944k memsize (     2.384k retained)
                              60.000  objects (     6.000  retained)
                               4.000  strings (     0.000  retained)
      ```
      
      After:
      
      ```
                      text   952.000  memsize (     0.000  retained)
                               9.000  objects (     0.000  retained)
                               1.000  strings (     0.000  retained)
                      html     1.008k memsize (     0.000  retained)
                              10.000  objects (     0.000  retained)
                               1.000  strings (     0.000  retained)
            text 1 default     2.400k memsize (    40.000  retained)
                              24.000  objects (     1.000  retained)
                               4.000  strings (     0.000  retained)
            html 1 default     2.464k memsize (     0.000  retained)
                              22.000  objects (     0.000  retained)
                               2.000  strings (     0.000  retained)
           text 2 defaults     3.232k memsize (     0.000  retained)
                              30.000  objects (     0.000  retained)
                               2.000  strings (     0.000  retained)
           html 2 defaults     3.456k memsize (     0.000  retained)
                              32.000  objects (     0.000  retained)
                               2.000  strings (     0.000  retained)
      ```
      
      **Speed**
      
      ```ruby
      require "benchmark/ips"
      
      Benchmark.ips do |x|
        x.report("text") { translate(:"translations.foo") }
        x.report("html") { translate(:"translations.html") }
        x.report("text 1 default") { translate(:"translations.missing", default: :"translations.foo") }
        x.report("html 1 default") { translate(:"translations.missing", default: :"translations.html") }
        x.report("text 2 defaults") { translate(:"translations.missing", default: [:"translations.missing", :"translations.foo"]) }
        x.report("html 2 defaults") { translate(:"translations.missing", default: [:"translations.missing", :"translations.html"]) }
      end
      ```
      
      Before:
      
      ```
                      text     35.685k (± 0.7%) i/s -    179.050k in   5.017773s
                      html     28.569k (± 3.1%) i/s -    143.871k in   5.040128s
            text 1 default     13.953k (± 2.0%) i/s -     70.737k in   5.071651s
            html 1 default     12.507k (± 0.4%) i/s -     63.546k in   5.080908s
           text 2 defaults      9.103k (± 0.3%) i/s -     46.308k in   5.087323s
           html 2 defaults      8.570k (± 4.3%) i/s -     43.071k in   5.034322s
      ```
      
      After:
      
      ```
                      text     36.694k (± 2.0%) i/s -    186.864k in   5.094367s
                      html     30.415k (± 0.5%) i/s -    152.900k in   5.027226s
            text 1 default     18.095k (± 2.7%) i/s -     91.086k in   5.036857s
            html 1 default     15.934k (± 1.7%) i/s -     80.223k in   5.036085s
           text 2 defaults     12.179k (± 0.6%) i/s -     61.659k in   5.062910s
           html 2 defaults     11.193k (± 2.1%) i/s -     56.406k in   5.041433s
      ```
      d81926fd
  2. 12 9月, 2020 1 次提交
    • J
      Refactor Action View `translate` helper · 98a76a50
      Jonathan Hefner 提交于
      This refactor incidentally fixes a corner case when `translate` is
      called with a block, the translation is missing, and
      `debug_missing_translation` is false.
      
      This commit adds a test for the above corner case, and additional tests
      for existing behavior.
      98a76a50
  3. 10 9月, 2020 1 次提交
    • J
      Merge pull request from GHSA-cfjv-5498-mph5 · e663f084
      Jonathan Hefner 提交于
      Prior to this commit, when a translation key indicated that the
      translation text was HTML, the value returned by `I18n.translate` would
      always be marked as `html_safe`.  However, the value returned by
      `I18n.translate` could be an untrusted value directly from
      `options[:default]`.
      
      This commit ensures values directly from `options[:default]` are not
      marked as `html_safe`.
      e663f084
  4. 27 8月, 2020 2 次提交
    • R
      Remove unecessary method call · 0edc6c8f
      Rafael Mendonça França 提交于
      All branches that use translated_text are covered so we can remove this
      method call.
      
      Also apply some whitespaces around conditionals to make them explicit.
      0edc6c8f
    • S
      Extend `ActionView::Helpers#translate` to yield · 7cf52ae9
      Sean Doyle 提交于
      This commit extends the `ActionView::Helpers#translate` (and by way of
      alias, `#t`) helper methods to accept blocks.
      
      When invoked with a block, the `translate` call will yield the
      translated text as its first block argument, along with the resolved
      translation key as its second:
      
      ```erb
      <%= translate(".key") do |translation, resolved_key| %>
        <span data-i18n-key="<%= resolved_key %>"><%= translation %></span>
      <% end %>
      ```
      
      In cases where relative translation keys are foregone in lieu of fully
      qualified keys, or if the caller is not interested in the resolved key,
      the second block argument can be omitted:
      
      ```erb
      <%= translate("action.template.key") do |translation| %>
        <p><%= translation %></p>
        <p><%= translation %>, but a second time</p>
      <% end %>
      ```
      
      A benefit of yielding the translation is that it enabled template-local
      variable re-use. Alternatively, [`Object#tap`][tap] could be used.
      
      Prior to this commit, however, the resolution of the translation key was
      internal to `ActionView`, and unavailable to the caller (unless they
      were willing to explicitly determine the resolved key themselves). By
      making it available as a block parameter, it could be used to annotate
      the translated value in the resulting elements.
      
      [tap]: https://ruby-doc.org/core-2.7.0/Object.html#method-i-tap
      7cf52ae9
  5. 27 5月, 2020 1 次提交
    • A
      Remove redundant @virtual_path variable · dd7a6737
      Aaron Lipman 提交于
      Following the introduction of the @current_template variable in 1581cab9,
      the @virtual_path variable is now redundant, as the value of the virtual
      path may be accessed via @current_template.virtual_path. This commit
      removes @virtual_path and replaces any references to @virtual_path with
      @current_template.virtual_path.
      dd7a6737
  6. 10 2月, 2020 1 次提交
    • S
      Fix translate method with default: nil · 8877b5ff
      Stefan Wrobel 提交于
          ```ruby
          I18n.translate('missing.translation', default: nil)
          # => nil
          helper.translate('missing.translation', default: nil)
          # Before
          # => "<span class=\"translation_missing\" title=\"translation missing: en.missing.translation\">Translation</span>"
          # After
          # => nil
          ```
      8877b5ff
  7. 05 2月, 2020 3 次提交
  8. 05 9月, 2019 1 次提交
  9. 14 6月, 2019 1 次提交
    • J
      Fix TranslationHelper#translate handling of Hash defaults · 5d4a77d3
      Jean Boussier 提交于
      It is sometimes expected of the `translate` methods to return a Hash,
      for instance it's the case of the `number.format` key.
      
      As such users might need to specify a Hash default, e.g.
      
      `translate(:'some.format', default: { separator: '.', delimiter: ',' })`.
      
      This works as expected with the `I18n.translate` methods,
      however `TranslationHelper#translate` apply `Array()` on the default value.
      
      As a result the default value end up as `[:separator, '.', :delimiter, ',']`.
      5d4a77d3
  10. 09 3月, 2019 1 次提交
  11. 01 3月, 2019 1 次提交
    • X
      Removes unnecessary dot in regexp · 42ca13a9
      Xavier Noria 提交于
      A string S matches ([.]|\b)html if an only if matches \bhtml:
      
        * If S matches [.]html, then it matches \bhtml.
      
        * If S matches \bhtml, then it matches \bhtml.
      
      Reciprocally:
      
        * If S matches \bhtml, then it matches ([.]|\b)html.
      
      The character class can be removed, and since we are on it we remove the
      group too so that it is clear to a reader of the code that there is no
      grouping going on.
      
      References #35166.
      42ca13a9
  12. 05 2月, 2019 1 次提交
  13. 23 9月, 2018 1 次提交
    • Y
      Enable `Performance/UnfreezeString` cop · 1b86d901
      yuuji.yaginuma 提交于
      In Ruby 2.3 or later, `String#+@` is available and `+@` is faster than `dup`.
      
      ```ruby
      # frozen_string_literal: true
      
      require "bundler/inline"
      
      gemfile(true) do
        source "https://rubygems.org"
      
        gem "benchmark-ips"
      end
      
      Benchmark.ips do |x|
        x.report('+@') { +"" }
        x.report('dup') { "".dup }
        x.compare!
      end
      ```
      
      ```
      $ ruby -v benchmark.rb
      ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux]
      Warming up --------------------------------------
                        +@   282.289k i/100ms
                       dup   187.638k i/100ms
      Calculating -------------------------------------
                        +@      6.775M (± 3.6%) i/s -     33.875M in   5.006253s
                       dup      3.320M (± 2.2%) i/s -     16.700M in   5.032125s
      
      Comparison:
                        +@:  6775299.3 i/s
                       dup:  3320400.7 i/s - 2.04x  slower
      
      ```
      1b86d901
  14. 03 7月, 2018 1 次提交
  15. 28 4月, 2018 1 次提交
  16. 23 3月, 2018 1 次提交
    • D
      Only create an array with default options if we have default options · 38526059
      Dillon Welch 提交于
      If the options passed in don't have a default key, there's no point in
      creating an array from those empty results when we can just go straight
      to creating an empty array.
      
      Benchmarks:
      ```ruby
      master_version with false
      {:FREE=>-2497, :T_STRING=>52, :T_ARRAY=>2000, :T_HASH=>1000, :T_IMEMO=>1}
      master_version with true
      {:FREE=>-3001, :T_ARRAY=>2000, :T_HASH=>1000}
      fast_version with false
      {:FREE=>-1001, :T_ARRAY=>1000}
      fast_version with true
      {:FREE=>-3001, :T_ARRAY=>2000, :T_HASH=>1000}
      Warming up --------------------------------------
      master_version with false
                             104.985k i/100ms
      master_version with true
                             118.737k i/100ms
      fast_version with false
                             206.013k i/100ms
      fast_version with true
                             107.005k i/100ms
      Calculating -------------------------------------
      master_version with false
                                1.970M (±24.6%) i/s -      8.924M in   5.010302s
      master_version with true
                                2.152M (±12.4%) i/s -     10.686M in   5.051588s
      fast_version with false
                                5.613M (±19.6%) i/s -     26.782M in   5.003740s
      fast_version with true
                                2.027M (±15.8%) i/s -      9.951M in   5.065670s
      
      Comparison:
      fast_version with false:  5613159.2 i/s
      master_version with true:  2152354.4 i/s - 2.61x  slower
      fast_version with true:  2027296.0 i/s - 2.77x  slower
      master_version with false:  1969824.9 i/s - 2.85x  slower
      ```
      
      Benchmark code:
      ```ruby
      begin
        require "bundler/inline"
      rescue LoadError => e
        $stderr.puts "Bundler version 1.10 or later is required. Please update
                      your Bundler"
        raise e
      end
      
      gemfile(true) do
        source "https://rubygems.org"
      
        gem "benchmark-ips"
        gem "rails"
      end
      
      def allocate_count
        GC.disable
        before = ObjectSpace.count_objects
        yield
        after = ObjectSpace.count_objects
        after.each { |k,v| after[k] = v - before[k] }
        after[:T_HASH] -= 1 # probe effect - we created the before hash.
        GC.enable
        result = after.reject { |k,v| v == 0 }
        GC.start
        result
      end
      
      def master_version(key)
        Array({}.delete(:default)).compact
      end
      
      def fast_version(key)
        if key
          Array({}.delete(:default)).compact
        else
          []
        end
      end
      
      def test
        puts "master_version with false"
        puts allocate_count { 1000.times { master_version(false) } }
        puts "master_version with true"
        puts allocate_count { 1000.times { master_version(true) } }
        puts "fast_version with false"
        puts allocate_count { 1000.times { fast_version(false) } }
        puts "fast_version with true"
        puts allocate_count { 1000.times { fast_version(true) } }
      
        Benchmark.ips do |x|
          x.report("master_version with false")  { master_version(false) }
          x.report("master_version with true") { master_version(true) }
          x.report("fast_version with false")    { fast_version(false) }
          x.report("fast_version with true")   { fast_version(true) }
          x.compare!
        end
      end
      
      test
      ```
      38526059
  17. 20 3月, 2018 1 次提交
    • D
      Memoize the result of gsubbing @virtual_path · 05eaa076
      Dillon Welch 提交于
      This gets called many times for each virtual_path, creating a new string
      each time that `translate` is called. We can memoize this so that it
      only happens once per virtual_path instead.
      05eaa076
  18. 21 10月, 2017 1 次提交
  19. 27 8月, 2017 1 次提交
  20. 24 7月, 2017 1 次提交
  21. 02 7月, 2017 1 次提交
  22. 01 7月, 2017 2 次提交
  23. 20 6月, 2017 1 次提交
  24. 03 6月, 2017 1 次提交
  25. 27 10月, 2016 1 次提交
    • X
      let Regexp#match? be globally available · 56832e79
      Xavier Noria 提交于
      Regexp#match? should be considered to be part of the Ruby core library. We are
      emulating it for < 2.4, but not having to require the extension is part of the
      illusion of the emulation.
      56832e79
  26. 07 8月, 2016 1 次提交
  27. 25 7月, 2016 1 次提交
  28. 19 12月, 2015 1 次提交
    • S
      debug_missing_translation configuration added to action_view · c1dbb13e
      Sameer Rahmani 提交于
      `I18n.translate` helper will wrap the missing translation keys
      in a <span> tag only if `debug_missing_translation` configuration has
      a truthy value. Default value is `true`. For example in `application.rb`:
      
          # in order to turn off missing key wrapping
          config.action_view.debug_missing_translation = false
      c1dbb13e
  29. 29 10月, 2015 1 次提交
  30. 19 9月, 2015 1 次提交
  31. 05 5月, 2015 2 次提交
  32. 24 4月, 2015 1 次提交
    • D
      Correct translate helper docs [ci skip] · 6ad5e7eb
      Derek Prior 提交于
      The documentation previously stated that calling `translate(".foo")` was
      equivalent to calling `I18n.translate("people.index.foo")` which is
      incorrect due to the various other functions of the `translate` view
      helper. This has been fixed.
      
      Additionally, a note about forcing the view helper to re-raise
      exceptions was added to the section detailing the handling of missing
      translations.
      
      Other cleanup includes:
      
      * Consistent formatting of code
      * Stop indenting bulleted list as a code sample
      * Tighten some of the language
      * Wrap at 80 characters.
      6ad5e7eb
  33. 05 4月, 2015 1 次提交
    • A
      Allow an array to be a default translation value. · 6f3c65f6
      Adam Prescott 提交于
      4.2.1 introduced a change to the way `translate`/`t` works with an
      option of `default: [[]]`. In 4.2.0, this would give a default value of
      `[]`, but in 4.2.1, it leads to a missing translation.
      
      `default: [[]]` is again allowed for cases where a default of `[]` is
      needed.
      
      This addresses GitHub issue 19640.
      6f3c65f6
  34. 21 3月, 2015 1 次提交
  35. 27 2月, 2015 1 次提交
    • U
      Fix regression when passing a value different of String. · 362557eb
      Ulisses Almeida 提交于
      The previous version of rails(4.2.0) you can pass objects
      to the default option of translation helper.
      
      For example:
      
      ```ruby
        t('foo', default: 1)
      ```
      
      But on rails 4.2.1 version this kind of use stopped to work,
      because started only to accept String types.
      
      Now with this fix we can use orther value types on this
      helper again.
      362557eb