Skip to content

Commit 9bcca2f

Browse files
kennyadslaldesantis
authored andcommitted
Introduce support for deprecating translation keys
Adds an `I18n::deprecate` API that allows users to mark a key as deprecated and superseded by another. `I18n::t` will then use the following logic: - If the key supersedes a deprecated one, and the old one is still defined, use the old one instead. If the old one is not defined anymore, use the new one. - If the key is deprecated and the old one is still defined, use the old one. If the old one is not defined anymore, use the new one. - For all other keys, regular behavior is maintained. The reason the old key is always preferred to the new one when available is that users may have been using the new key for other purposes, and we don't want to swap it for the old one without notice. Instead, users have to manually go in and delete the old key for the new one to start being used.
1 parent 2942126 commit 9bcca2f

File tree

6 files changed

+85
-1
lines changed

6 files changed

+85
-1
lines changed

lib/i18n.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,10 @@ def translate(key = nil, *, throw: false, raise: false, locale: nil, **options)
199199
end
200200
alias :t :translate
201201

202+
def deprecate(deprecation)
203+
config.deprecations[deprecation.keys.first.to_sym] = deprecation.values.first.to_sym
204+
end
205+
202206
# Wrapper for <tt>translate</tt> that adds <tt>:raise => true</tt>. With
203207
# this option, if no translation is found, it will raise <tt>I18n::MissingTranslationData</tt>
204208
def translate!(key, options = EMPTY_HASH)

lib/i18n/backend.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ module Backend
88
autoload :CacheFile, 'i18n/backend/cache_file'
99
autoload :Cascade, 'i18n/backend/cascade'
1010
autoload :Chain, 'i18n/backend/chain'
11+
autoload :Deprecator, 'i18n/backend/deprecator'
1112
autoload :Fallbacks, 'i18n/backend/fallbacks'
1213
autoload :Flatten, 'i18n/backend/flatten'
1314
autoload :Gettext, 'i18n/backend/gettext'

lib/i18n/backend/base.rb

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,30 @@ def translate(locale, key, options = EMPTY_HASH)
2929
raise InvalidLocale.new(locale) unless locale
3030
return nil if key.nil? && !options.key?(:default)
3131

32-
entry = lookup(locale, key, options[:scope], options) unless key.nil?
32+
entry = nil
33+
34+
unless key.nil?
35+
normalized_key = I18n.normalize_keys(locale, key, options[:scope])[1..-1].join(I18n.config.default_separator).to_sym
36+
deprecated_key = I18n.config.deprecations.key(normalized_key)
37+
38+
# Does this key supersede a deprecated one?
39+
if deprecated_key
40+
# Try to use up the old key, if present.
41+
entry = lookup(locale, deprecated_key, nil, options)
42+
end
43+
44+
entry ||= lookup(locale, key, options[:scope], options)
45+
46+
if entry.nil?
47+
# Is this key deprecated by another?
48+
new_key = I18n.config.deprecations[normalized_key]
49+
50+
if new_key
51+
puts "DEPRECATION WARNING: #{normalized_key} is deprecated, use #{new_key} instead"
52+
entry = lookup(locale, new_key, nil, options)
53+
end
54+
end
55+
end
3356

3457
if entry.nil? && options.key?(:default)
3558
entry = default(locale, key, options[:default], options)

lib/i18n/backend/deprecator.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# frozen_string_literal: true
2+
3+
module I18n
4+
module Backend
5+
module Deprecator
6+
def store_translations(locale, data, options = EMPTY_HASH)
7+
super
8+
9+
I18n.config.deprecations.each do |deprecated_key, new_key|
10+
if lookup(locale, deprecated_key)
11+
puts "DEPRECATION WARNING: #{deprecated_key} is deprecated, use #{new_key} instead"
12+
end
13+
end
14+
end
15+
end
16+
end
17+
end

lib/i18n/config.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ def backend=(backend)
2626
@@backend = backend
2727
end
2828

29+
def deprecations
30+
@@deprecations ||= {}
31+
end
32+
2933
# Returns the current default locale. Defaults to :'en'
3034
def default_locale
3135
@@default_locale ||= :en

test/backend/deprecator_test.rb

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
require 'test_helper'
2+
3+
class I18nBackendDeprecatorTest < I18n::TestCase
4+
class Backend < I18n::Backend::Simple
5+
include I18n::Backend::Deprecator
6+
include I18n::Backend::Fallbacks
7+
end
8+
9+
def setup
10+
super
11+
I18n.backend = Backend.new
12+
I18n.deprecate(old_key: :new_key)
13+
end
14+
15+
test 'old key defined, new key undefined' do
16+
store_translations(:xx, old_key: 'Hello world')
17+
18+
assert_equal 'Hello world', I18n.t(:old_key, locale: :xx)
19+
assert_equal 'Hello world', I18n.t(:new_key, locale: :xx)
20+
end
21+
22+
test 'old key undefined, new key defined' do
23+
store_translations(:xx, new_key: 'Hello new world')
24+
25+
assert_equal 'Hello new world', I18n.t(:old_key, locale: :xx)
26+
assert_equal 'Hello new world', I18n.t(:new_key, locale: :xx)
27+
end
28+
29+
test 'old key defined, new key defined' do
30+
store_translations(:xx, old_key: 'Hello world', new_key: 'Hello new world')
31+
32+
assert_equal 'Hello world', I18n.t(:old_key, locale: :xx)
33+
assert_equal 'Hello world', I18n.t(:new_key, locale: :xx)
34+
end
35+
end

0 commit comments

Comments
 (0)