diff --git a/app/models/translation_override.rb b/app/models/translation_override.rb new file mode 100644 index 00000000000..a7c927318cf --- /dev/null +++ b/app/models/translation_override.rb @@ -0,0 +1,11 @@ +class TranslationOverride < ActiveRecord::Base + validates_uniqueness_of :translation_key, scope: :locale + validates_presence_of :locale, :translation_key, :value + + def self.upsert!(locale, key, value) + params = { locale: locale, translation_key: key } + row_count = where(params).update_all(value: value) + create!(params.merge(value: value)) if row_count == 0 + end + +end diff --git a/db/migrate/20151113205046_create_translation_overrides.rb b/db/migrate/20151113205046_create_translation_overrides.rb new file mode 100644 index 00000000000..48f7bcb3f7c --- /dev/null +++ b/db/migrate/20151113205046_create_translation_overrides.rb @@ -0,0 +1,12 @@ +class CreateTranslationOverrides < ActiveRecord::Migration + def change + create_table :translation_overrides, force: true do |t| + t.string :locale, length: 30, null: false + t.string :translation_key, null: false + t.string :value, null: false + t.timestamps null: false + end + + add_index :translation_overrides, [:locale, :translation_key], unique: true + end +end diff --git a/lib/i18n/backend/discourse_i18n.rb b/lib/i18n/backend/discourse_i18n.rb index 9e34866d0b3..e76c1c5edda 100644 --- a/lib/i18n/backend/discourse_i18n.rb +++ b/lib/i18n/backend/discourse_i18n.rb @@ -12,6 +12,24 @@ module I18n LocaleSiteSetting.supported_locales.map(&:to_sym) end + def reload! + @overrides = {} + super + end + + def overrides_for(locale) + @overrides ||= {} + return @overrides[locale] if @overrides[locale] + + @overrides[locale] = {} + + TranslationOverride.where(locale: locale).pluck(:translation_key, :value).each do |tuple| + @overrides[locale][tuple[0]] = tuple[1] + end + + @overrides[locale] + end + # force explicit loading def load_translations(*filenames) unless filenames.empty? @@ -23,6 +41,10 @@ module I18n [locale, SiteSetting.default_locale.to_sym, :en].uniq.compact end + def translate(locale, key, options = {}) + overrides_for(locale)[key] || super(locale, key, options) + end + def exists?(locale, key) fallbacks(locale).each do |fallback| begin diff --git a/spec/components/discourse_i18n_spec.rb b/spec/components/discourse_i18n_spec.rb index 98888fa42b1..6f2f02813a3 100644 --- a/spec/components/discourse_i18n_spec.rb +++ b/spec/components/discourse_i18n_spec.rb @@ -1,11 +1,13 @@ require 'spec_helper' require 'i18n/backend/discourse_i18n' +require 'translation_override' describe I18n::Backend::DiscourseI18n do let(:backend) { I18n::Backend::DiscourseI18n.new } before do + backend.reload! backend.store_translations(:en, :foo => 'Foo in :en', :bar => 'Bar in :en') backend.store_translations(:en, :items => {:one => 'one item', :other => "%{count} items" }) backend.store_translations(:de, :bar => 'Bar in :de') @@ -50,4 +52,18 @@ describe I18n::Backend::DiscourseI18n do end end + describe 'with overrides' do + before do + TranslationOverride.upsert!('en', 'foo', 'Overwritten foo') + end + + it 'returns the overrided key' do + expect(backend.translate(:en, 'foo')).to eq('Overwritten foo') + + TranslationOverride.upsert!('en', 'foo', 'new value') + backend.reload! + expect(backend.translate(:en, 'foo')).to eq('new value') + end + end + end