Skip to content

Commit

Permalink
Deprecate {{}} as interpolation syntax.
Browse files Browse the repository at this point in the history
  • Loading branch information
josevalim committed Apr 30, 2010
1 parent 4f9592f commit 8894ee5
Show file tree
Hide file tree
Showing 15 changed files with 103 additions and 342 deletions.
40 changes: 20 additions & 20 deletions benchmark/example.yml
Expand Up @@ -15,23 +15,23 @@ en:
accepted: "must be accepted"
empty: "can't be empty"
blank: "can't be blank"
too_long: "is too long (maximum is {{count}} characters)"
too_short: "is too short (minimum is {{count}} characters)"
wrong_length: "is the wrong length (should be {{count}} characters)"
too_long: "is too long (maximum is %{count} characters)"
too_short: "is too short (minimum is %{count} characters)"
wrong_length: "is the wrong length (should be %{count} characters)"
taken: "has already been taken"
not_a_number: "is not a number"
greater_than: "must be greater than {{count}}"
greater_than_or_equal_to: "must be greater than or equal to {{count}}"
equal_to: "must be equal to {{count}}"
less_than: "must be less than {{count}}"
less_than_or_equal_to: "must be less than or equal to {{count}}"
greater_than: "must be greater than %{count}"
greater_than_or_equal_to: "must be greater than or equal to %{count}"
equal_to: "must be equal to %{count}"
less_than: "must be less than %{count}"
less_than_or_equal_to: "must be less than or equal to %{count}"
odd: "must be odd"
even: "must be even"
record_invalid: "Validation failed: {{errors}}"
record_invalid: "Validation failed: %{errors}"

models:
user:
blank: "This is a custom blank message for {{model}}: {{attribute}}"
blank: "This is a custom blank message for %{model}: %{attribute}"
attributes:
login:
blank: "This is a custom blank message for User login"
Expand Down Expand Up @@ -86,23 +86,23 @@ en:
accepted: "must be accepted"
empty: "can't be empty"
blank: "can't be blank"
too_long: "is too long (maximum is {{count}} characters)"
too_short: "is too short (minimum is {{count}} characters)"
wrong_length: "is the wrong length (should be {{count}} characters)"
too_long: "is too long (maximum is %{count} characters)"
too_short: "is too short (minimum is %{count} characters)"
wrong_length: "is the wrong length (should be %{count} characters)"
taken: "has already been taken"
not_a_number: "is not a number"
greater_than: "must be greater than {{count}}"
greater_than_or_equal_to: "must be greater than or equal to {{count}}"
equal_to: "must be equal to {{count}}"
less_than: "must be less than {{count}}"
less_than_or_equal_to: "must be less than or equal to {{count}}"
greater_than: "must be greater than %{count}"
greater_than_or_equal_to: "must be greater than or equal to %{count}"
equal_to: "must be equal to %{count}"
less_than: "must be less than %{count}"
less_than_or_equal_to: "must be less than or equal to %{count}"
odd: "must be odd"
even: "must be even"
record_invalid: "Validation failed: {{errors}}"
record_invalid: "Validation failed: %{errors}"

models:
user:
blank: "This is a custom blank message for {{model}}: {{attribute}}"
blank: "This is a custom blank message for %{model}: %{attribute}"
attributes:
login:
blank: "This is a custom blank message for User login"
Expand Down
13 changes: 1 addition & 12 deletions benchmark/run.rb
Expand Up @@ -17,17 +17,6 @@ module Backends
include I18n::Backend::Fast
end.new

Interpolation = Class.new do
include I18n::Backend::Base
include I18n::Backend::InterpolationCompiler
end.new

FastInterpolation = Class.new do
include I18n::Backend::Base
include I18n::Backend::Fast
include I18n::Backend::InterpolationCompiler
end.new

if DATA_STORES
require 'rubygems'
require File.expand_path('../../test/test_setup_requirements', __FILE__)
Expand All @@ -40,7 +29,7 @@ module Backends
end
end

ORDER = %w(Simple Fast Interpolation FastInterpolation ActiveRecord TokyoCabinet)
ORDER = %w(Simple Fast ActiveRecord TokyoCabinet)
ORDER.map!(&:to_sym) if RUBY_VERSION > '1.9'

module Benchmark
Expand Down
6 changes: 3 additions & 3 deletions lib/i18n.rb
Expand Up @@ -80,7 +80,7 @@ def reload!
# values passed to #translate as part of the options hash, with the keys matching
# the interpolation variable names.
#
# <em>E.g.</em>, with a translation <tt>:foo => "foo {{bar}}"</tt> the option
# <em>E.g.</em>, with a translation <tt>:foo => "foo %{bar}"</tt> the option
# value for the key +bar+ will be interpolated into the translation:
# I18n.t :foo, :bar => 'baz' # => 'foo baz'
#
Expand All @@ -101,7 +101,7 @@ def reload!
#
# The <tt>:count</tt> option can be used both for pluralization and interpolation.
# <em>E.g.</em>, with the translation
# <tt>:foo => ['{{count}} foo', '{{count}} foos']</tt>, count will
# <tt>:foo => ['%{count} foo', '%{count} foos']</tt>, count will
# be interpolated to the pluralized translation:
# I18n.t :foo, :count => 1 # => '1 foo'
#
Expand Down Expand Up @@ -135,7 +135,7 @@ def reload!
# called and passed the key and options.
#
# E.g. assuming the key <tt>:salutation</tt> resolves to:
# lambda { |key, options| options[:gender] == 'm' ? "Mr. {{options[:name]}}" : "Mrs. {{options[:name]}}" }
# lambda { |key, options| options[:gender] == 'm' ? "Mr. %{options[:name]}" : "Mrs. %{options[:name]}" }
#
# Then <tt>I18n.t(:salutation, :gender => 'w', :name => 'Smith') will result in "Mrs. Smith".
#
Expand Down
1 change: 0 additions & 1 deletion lib/i18n/backend.rb
Expand Up @@ -10,7 +10,6 @@ module Backend
autoload :Fast, 'i18n/backend/fast'
autoload :Flatten, 'i18n/backend/flatten'
autoload :Gettext, 'i18n/backend/gettext'
autoload :InterpolationCompiler, 'i18n/backend/interpolation_compiler'
autoload :KeyValue, 'i18n/backend/key_value'
autoload :Metadata, 'i18n/backend/metadata'
autoload :Pluralization, 'i18n/backend/pluralization'
Expand Down
5 changes: 3 additions & 2 deletions lib/i18n/backend/base.rb
Expand Up @@ -178,8 +178,8 @@ def pluralize(locale, entry, count)

# Interpolates values into a given string.
#
# interpolate "file {{file}} opened by \\{{user}}", :file => 'test.txt', :user => 'Mr. X'
# # => "file test.txt opened by {{user}}"
# interpolate "file %{file} opened by %%{user}", :file => 'test.txt', :user => 'Mr. X'
# # => "file test.txt opened by %{user}"
#
# Note that you have to double escape the <tt>\\</tt> when you want to escape
# the <tt>{{...}}</tt> key in a string (once for the string and once for the
Expand All @@ -195,6 +195,7 @@ def interpolate(locale, string, values = {})
elsif RESERVED_KEYS.include?(key)
raise ReservedInterpolationKey.new(key, string)
else
warn "The {{key}} interpolation syntax in I18n messages is deprecated. Please use %{key} instead."
"%{#{key}}"
end
end
Expand Down
119 changes: 0 additions & 119 deletions lib/i18n/backend/interpolation_compiler.rb

This file was deleted.

1 change: 0 additions & 1 deletion test/api/all_features_test.rb
Expand Up @@ -19,7 +19,6 @@ class Backend
include I18n::Backend::Fallbacks
include I18n::Backend::Pluralization
include I18n::Backend::Fast
include I18n::Backend::InterpolationCompiler
end

def setup
Expand Down
30 changes: 15 additions & 15 deletions test/api/tests/interpolation.rb
Expand Up @@ -10,19 +10,19 @@ def interpolate(*args)
end

define_method "test interpolation: given no values it does not alter the string" do
assert_equal 'Hi {{name}}!', interpolate(:default => 'Hi {{name}}!')
assert_equal 'Hi %{name}!', interpolate(:default => 'Hi %{name}!')
end

define_method "test interpolation: given values it interpolates them into the string" do
assert_equal 'Hi David!', interpolate(:default => 'Hi {{name}}!', :name => 'David')
assert_equal 'Hi David!', interpolate(:default => 'Hi %{name}!', :name => 'David')
end

define_method "test interpolation: given a nil value it still interpolates it into the string" do
assert_equal 'Hi !', interpolate(:default => 'Hi {{name}}!', :name => nil)
assert_equal 'Hi !', interpolate(:default => 'Hi %{name}!', :name => nil)
end

define_method "test interpolation: given a lambda as a value it calls it if the string contains the key" do
assert_equal 'Hi David!', interpolate(:default => 'Hi {{name}}!', :name => lambda { |*args| 'David' })
assert_equal 'Hi David!', interpolate(:default => 'Hi %{name}!', :name => lambda { |*args| 'David' })
end

define_method "test interpolation: given a lambda as a value it does not call it if the string does not contain the key" do
Expand All @@ -31,53 +31,53 @@ def interpolate(*args)

define_method "test interpolation: given values but missing a key it raises I18n::MissingInterpolationArgument" do
assert_raise(I18n::MissingInterpolationArgument) do
interpolate(:default => '{{foo}}', :bar => 'bar')
interpolate(:default => '%{foo}', :bar => 'bar')
end
end

define_method "test interpolation: it does not raise I18n::MissingInterpolationArgument for escaped variables" do
assert_nothing_raised(I18n::MissingInterpolationArgument) do
assert_equal 'Barr {{foo}}', interpolate(:default => '{{bar}} \{{foo}}', :bar => 'Barr')
assert_equal 'Barr %{foo}', interpolate(:default => '%{bar} %%{foo}', :bar => 'Barr')
end
end

define_method "test interpolation: it does not change the original, stored translation string" do
I18n.backend.store_translations(:en, :interpolate => 'Hi {{name}}!')
I18n.backend.store_translations(:en, :interpolate => 'Hi %{name}!')
assert_equal 'Hi David!', interpolate(:interpolate, :name => 'David')
assert_equal 'Hi Yehuda!', interpolate(:interpolate, :name => 'Yehuda')
end

define_method "test interpolation: works with Ruby 1.9 syntax" do
assert_equal 'Hi David!', interpolate(:default => 'Hi %{name}!', :name => 'David')
define_method "test interpolation: works with the deprecated syntax" do
assert_equal 'Hi David!', interpolate(:default => 'Hi {{name}}!', :name => 'David')
end

define_method "test interpolation: given the translation is in utf-8 it still works" do
assert_equal 'Häi David!', interpolate(:default => 'Häi {{name}}!', :name => 'David')
assert_equal 'Häi David!', interpolate(:default => 'Häi %{name}!', :name => 'David')
end

define_method "test interpolation: given the value is in utf-8 it still works" do
assert_equal 'Hi ゆきひろ!', interpolate(:default => 'Hi {{name}}!', :name => 'ゆきひろ')
assert_equal 'Hi ゆきひろ!', interpolate(:default => 'Hi %{name}!', :name => 'ゆきひろ')
end

define_method "test interpolation: given the translation and the value are in utf-8 it still works" do
assert_equal 'こんにちは、ゆきひろさん!', interpolate(:default => 'こんにちは、{{name}}さん!', :name => 'ゆきひろ')
assert_equal 'こんにちは、ゆきひろさん!', interpolate(:default => 'こんにちは、%{name}さん!', :name => 'ゆきひろ')
end

if Kernel.const_defined?(:Encoding)
define_method "test interpolation: given a euc-jp translation and a utf-8 value it raises Encoding::CompatibilityError" do
assert_raise(Encoding::CompatibilityError) do
interpolate(:default => euc_jp('こんにちは、{{name}}さん!'), :name => 'ゆきひろ')
interpolate(:default => euc_jp('こんにちは、%{name}さん!'), :name => 'ゆきひろ')
end
end

# define_method "test interpolation: given a utf-8 translation and a euc-jp value it returns a translation in euc-jp" do
# assert_equal euc_jp('Hi ゆきひろ!'), interpolate(:default => 'Hi {{name}}!', :name => euc_jp('ゆきひろ'))
# assert_equal euc_jp('Hi ゆきひろ!'), interpolate(:default => 'Hi %{name}!', :name => euc_jp('ゆきひろ'))
# end
#
# TODO should better explain how this relates to the test above with the simpler utf-8 default string
define_method "test interpolation: given a utf-8 translation and a euc-jp value it raises Encoding::CompatibilityError" do
assert_raise(Encoding::CompatibilityError) do
interpolate(:default => 'こんにちは、{{name}}さん!', :name => euc_jp('ゆきひろ'))
interpolate(:default => 'こんにちは、%{name}さん!', :name => euc_jp('ゆきひろ'))
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions test/api/tests/procs.rb
Expand Up @@ -25,11 +25,11 @@ module Procs

define_method "test interpolation: given an interpolation value is a lambda it calls it with key and values before interpolating it" do
proc = lambda { |*args| args.inspect }
assert_match %r(\[\{:foo=>#<Proc.*>\}\]), I18n.t(nil, :default => '{{foo}}', :foo => proc)
assert_match %r(\[\{:foo=>#<Proc.*>\}\]), I18n.t(nil, :default => '%{foo}', :foo => proc)
end

define_method "test interpolation: given a key resolves to a Proc that returns a string then interpolation still works" do
proc = lambda { |*args| "{{foo}}: " + args.inspect }
proc = lambda { |*args| "%{foo}: " + args.inspect }
assert_equal 'foo: [nil, {:foo=>"foo"}]', I18n.t(nil, :default => proc, :foo => 'foo')
end

Expand Down
4 changes: 2 additions & 2 deletions test/backend/chain_test.rb
Expand Up @@ -5,7 +5,7 @@
class I18nBackendChainTest < Test::Unit::TestCase
def setup
@first = backend(:en => {
:foo => 'Foo', :formats => { :short => 'short' }, :plural_1 => { :one => '{{count}}' }
:foo => 'Foo', :formats => { :short => 'short' }, :plural_1 => { :one => '%{count}' }
})
@second = backend(:en => {
:bar => 'Bar', :formats => { :long => 'long' }, :plural_2 => { :one => 'one' }
Expand Down Expand Up @@ -41,7 +41,7 @@ def setup
end

test "namespace lookup with only the first backend returning a result" do
assert_equal({ :one => '{{count}}' }, I18n.t(:plural_1))
assert_equal({ :one => '%{count}' }, I18n.t(:plural_1))
end

test "pluralization still works" do
Expand Down

3 comments on commit 8894ee5

@grimen
Copy link

@grimen grimen commented on 8894ee5 May 1, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whop-whop! B)

@roidrage
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank goodness, I hated that syntax :)

@knapo
Copy link
Collaborator

@knapo knapo commented on 8894ee5 May 9, 2010

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, the only thing I don't like are two INTERPOLATION_SYNTAX_PATTERN constants, one in Base backend and another in InterpolationCompiler, which are different. I would rename the first one to e.g. DEPRACATED_INTERPOLATION_SYNTAX_PATTERN and keep both in one place. What do you think Jose?

Please sign in to comment.