Improved initial import and sync of translations (about 5-8 times faster).
This commit is contained in:
parent
b58fcbb5fc
commit
5bfa535b62
4 changed files with 121 additions and 41 deletions
1
Gemfile
1
Gemfile
|
@ -5,6 +5,7 @@ ruby '2.4.4'
|
||||||
gem 'rails', '5.1.5'
|
gem 'rails', '5.1.5'
|
||||||
|
|
||||||
# core - rails additions
|
# core - rails additions
|
||||||
|
gem 'activerecord-import'
|
||||||
gem 'activerecord-session_store'
|
gem 'activerecord-session_store'
|
||||||
gem 'composite_primary_keys'
|
gem 'composite_primary_keys'
|
||||||
gem 'json'
|
gem 'json'
|
||||||
|
|
|
@ -49,6 +49,8 @@ GEM
|
||||||
activemodel (= 5.1.5)
|
activemodel (= 5.1.5)
|
||||||
activesupport (= 5.1.5)
|
activesupport (= 5.1.5)
|
||||||
arel (~> 8.0)
|
arel (~> 8.0)
|
||||||
|
activerecord-import (0.25.0)
|
||||||
|
activerecord (>= 3.2)
|
||||||
activerecord-nulldb-adapter (0.3.7)
|
activerecord-nulldb-adapter (0.3.7)
|
||||||
activerecord (>= 2.0.0)
|
activerecord (>= 2.0.0)
|
||||||
activerecord-session_store (1.1.0)
|
activerecord-session_store (1.1.0)
|
||||||
|
@ -486,6 +488,7 @@ PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
|
activerecord-import
|
||||||
activerecord-nulldb-adapter
|
activerecord-nulldb-adapter
|
||||||
activerecord-session_store
|
activerecord-session_store
|
||||||
argon2
|
argon2
|
||||||
|
|
|
@ -342,46 +342,38 @@ Get source file at https://i18n.zammad.com/api/v1/translations_empty_translation
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.remote_translation_need_update?(raw, translations)
|
||||||
|
translations.each do |row|
|
||||||
|
next if row[1] != raw['locale']
|
||||||
|
next if row[2] != raw['source']
|
||||||
|
next if row[3] != raw['format']
|
||||||
|
return false if row[4] == raw['target'] # no update if target is still the same
|
||||||
|
return false if row[4] != row[5] # no update if translation has already changed
|
||||||
|
return [true, Translation.find(row[0])]
|
||||||
|
end
|
||||||
|
[true, nil]
|
||||||
|
end
|
||||||
|
|
||||||
private_class_method def self.to_database(locale, data)
|
private_class_method def self.to_database(locale, data)
|
||||||
translations = Translation.where(locale: locale).all
|
translations = Translation.where(locale: locale).pluck(:id, :locale, :source, :format, :target, :target_initial).to_a
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
|
translations_to_import = []
|
||||||
data.each do |translation_raw|
|
data.each do |translation_raw|
|
||||||
|
result = Translation.remote_translation_need_update?(translation_raw, translations)
|
||||||
# handle case insensitive sql
|
next if result == false
|
||||||
translation = nil
|
next if result.class != Array
|
||||||
translations.each do |item|
|
if result[1]
|
||||||
next if item.format != translation_raw['format']
|
result[1].update!(translation_raw.symbolize_keys!)
|
||||||
next if item.source != translation_raw['source']
|
result[1].save
|
||||||
translation = item
|
|
||||||
break
|
|
||||||
end
|
|
||||||
if translation
|
|
||||||
|
|
||||||
# verify if update is needed
|
|
||||||
update_needed = false
|
|
||||||
translation_raw.each_key do |key|
|
|
||||||
|
|
||||||
# if translation target has changes
|
|
||||||
next if translation_raw[key] == translation.target
|
|
||||||
|
|
||||||
# do not update translations which are already changed by user
|
|
||||||
if translation.target == translation.target_initial
|
|
||||||
update_needed = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if update_needed
|
|
||||||
translation.update!(translation_raw.symbolize_keys!)
|
|
||||||
translation.save
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
if !UserInfo.current_user_id
|
translation_raw['updated_by_id'] = UserInfo.current_user_id || 1
|
||||||
translation_raw['updated_by_id'] = 1
|
translation_raw['created_by_id'] = UserInfo.current_user_id || 1
|
||||||
translation_raw['created_by_id'] = 1
|
translations_to_import.push Translation.new(translation_raw.symbolize_keys!)
|
||||||
end
|
|
||||||
Translation.create(translation_raw.symbolize_keys!)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if translations_to_import.present?
|
||||||
|
Translation.import translations_to_import
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -401,7 +393,7 @@ Get source file at https://i18n.zammad.com/api/v1/translations_empty_translation
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_initial
|
def set_initial
|
||||||
return true if target_initial
|
return true if target_initial.present?
|
||||||
return true if target_initial == ''
|
return true if target_initial == ''
|
||||||
self.target_initial = target
|
self.target_initial = target
|
||||||
true
|
true
|
||||||
|
|
|
@ -2,9 +2,10 @@ require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe Translation do
|
RSpec.describe Translation do
|
||||||
|
|
||||||
|
Translation.where(locale: 'de-de').destroy_all
|
||||||
|
Translation.sync('de-de')
|
||||||
|
|
||||||
context 'default translations' do
|
context 'default translations' do
|
||||||
Translation.reset('de-de')
|
|
||||||
Translation.sync('de-de')
|
|
||||||
|
|
||||||
it 'en with existing word' do
|
it 'en with existing word' do
|
||||||
expect(Translation.translate('en', 'New')).to eq('New')
|
expect(Translation.translate('en', 'New')).to eq('New')
|
||||||
|
@ -28,13 +29,82 @@ RSpec.describe Translation do
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'custom translation tests' do
|
context 'remote_translation_need_update? tests' do
|
||||||
Translation.where(locale: 'de-de').destroy_all
|
|
||||||
Translation.sync('de-de')
|
|
||||||
|
|
||||||
locale = 'de-de'
|
it 'translation is still the same' do
|
||||||
|
translation = Translation.where(locale: 'de-de', format: 'string').last
|
||||||
|
translations = Translation.where(locale: 'de-de').pluck(:id, :locale, :source, :format, :target, :target_initial).to_a
|
||||||
|
expect(
|
||||||
|
Translation.remote_translation_need_update?(
|
||||||
|
{
|
||||||
|
'source' => translation.source,
|
||||||
|
'format' => translation.format,
|
||||||
|
'locale' => translation.locale,
|
||||||
|
'target' => translation.target,
|
||||||
|
'target_initial' => translation.target_initial,
|
||||||
|
}, translations
|
||||||
|
)
|
||||||
|
).to be false
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'translation target has locally changed' do
|
||||||
|
translation = Translation.where(locale: 'de-de', format: 'string').last
|
||||||
|
translation.target = 'some new translation'
|
||||||
|
translation.save!
|
||||||
|
translations = Translation.where(locale: 'de-de').pluck(:id, :locale, :source, :format, :target, :target_initial).to_a
|
||||||
|
expect(
|
||||||
|
Translation.remote_translation_need_update?(
|
||||||
|
{
|
||||||
|
'source' => translation.source,
|
||||||
|
'format' => translation.format,
|
||||||
|
'locale' => translation.locale,
|
||||||
|
'target' => translation.target,
|
||||||
|
'target_initial' => translation.target_initial,
|
||||||
|
}, translations
|
||||||
|
)
|
||||||
|
).to be false
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'translation target has remotely changed' do
|
||||||
|
translation = Translation.where(locale: 'de-de', format: 'string').last
|
||||||
|
translations = Translation.where(locale: 'de-de').pluck(:id, :locale, :source, :format, :target, :target_initial).to_a
|
||||||
|
(result, translation_result) = Translation.remote_translation_need_update?(
|
||||||
|
{
|
||||||
|
'source' => translation.source,
|
||||||
|
'format' => translation.format,
|
||||||
|
'locale' => translation.locale,
|
||||||
|
'target' => 'some new translation by remote',
|
||||||
|
'target_initial' => 'some new translation by remote',
|
||||||
|
}, translations
|
||||||
|
)
|
||||||
|
expect(result).to be true
|
||||||
|
expect(translation_result.attributes).to eq translation.attributes
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'translation target has remotely and locally changed' do
|
||||||
|
translation = Translation.where(locale: 'de-de', format: 'string').last
|
||||||
|
translation.target = 'some new translation'
|
||||||
|
translation.save!
|
||||||
|
translations = Translation.where(locale: 'de-de').pluck(:id, :locale, :source, :format, :target, :target_initial).to_a
|
||||||
|
expect(
|
||||||
|
Translation.remote_translation_need_update?(
|
||||||
|
{
|
||||||
|
'source' => translation.source,
|
||||||
|
'format' => translation.format,
|
||||||
|
'locale' => translation.locale,
|
||||||
|
'target' => 'some new translation by remote',
|
||||||
|
'target_initial' => 'some new translation by remote',
|
||||||
|
}, translations
|
||||||
|
)
|
||||||
|
).to be false
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'custom translation tests' do
|
||||||
|
|
||||||
it 'cycle of change and reload translation' do
|
it 'cycle of change and reload translation' do
|
||||||
|
locale = 'de-de'
|
||||||
|
|
||||||
# check for non existing custom changes
|
# check for non existing custom changes
|
||||||
list = Translation.lang(locale)
|
list = Translation.lang(locale)
|
||||||
|
@ -123,4 +193,18 @@ RSpec.describe Translation do
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'sync duplicate tests' do
|
||||||
|
|
||||||
|
it 'check duplication of entries' do
|
||||||
|
Translation.where(locale: 'de-de').destroy_all
|
||||||
|
Translation.sync('de-de')
|
||||||
|
translation_count = Translation.where(locale: 'de-de').count
|
||||||
|
Translation.sync('de-de')
|
||||||
|
expect(
|
||||||
|
Translation.where(locale: 'de-de').count
|
||||||
|
).to be translation_count
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue