Maintenance: Improve handling of translation entries in extractor and on importing.

This commit is contained in:
Martin Gruner 2021-11-19 13:11:20 +01:00
parent 8a97a41dc9
commit 1f5d1bf8d3
14 changed files with 111 additions and 19 deletions

View file

@ -89,7 +89,7 @@ class Sla extends App.ControllerSubContent
description: (e) =>
new App.ControllerGenericDescription(
description: App.Calendar.description
description: App.Sla.description
container: @el.closest('.content')
)

View file

@ -23,8 +23,8 @@ class App.Sla extends App.Model
@description = __('''
** Service Level Agreements **, abbreviated ** SLAs **, help you to meet certain customers' time-related responses. Thus, for example, you can say customers should always get a response from you after 8 hours at the latest. In the event of an imminent violation or a breach, Zammad will alert you to such events.
''') + '\n\n' + __('''
It can be ** response time ** (time between the creation of a ticket and the first reaction of an agent), ** update time ** (time between a customer's request and an agent's reaction) and ** solution time ** (time between creation and closing a ticket ) To be defined.
''') + '\n\n' + __('''
Any violations are displayed in a separate view in the overviews. You can also configure ** e-mail notifications **.
''')

View file

@ -39,24 +39,22 @@ class App.TextModule extends App.Model
# coffeelint: disable=no_interpolation_in_single_quotes
@description = __('''
Create Text Modules to **spend less time writing responses**. Text Modules can include smart variables like the users name or email address.
''') + '\n\n' + __('''
Examples of snippets are:
* Hello Mrs. #{ticket.customer.lastname},
* Hello Mr. #{ticket.customer.lastname},
* Hello #{ticket.customer.firstname},
* My Name is #{user.firstname},
''') + '\n\n' + __('''
Of course you can also use multi line snippets.
''') + '\n\n' + __('''
Available objects are:
* ticket (e. g. ticket.state, ticket.group)
* ticket.customer (e. g. ticket.customer.firstname, ticket.customer.lastname)
* ticket.owner (e. g. ticket.owner.firstname, ticket.owner.lastname)
* ticket.organization (e. g. ticket.organization.name)
* user (e. g. user.firstname, user.email)
''') + '\n\n' + __('''
To select placeholders from a list, just enter "::".
''')
# coffeelint: enable=no_interpolation_in_single_quotes

View file

@ -17,8 +17,8 @@ class App.Trigger extends App.Model
@description = __('''
Every time a customer creates a new ticket, they automatically receive a confirmation email to assure them that their issue has been submitted successfully. This behavior is built into Zammad, but its also highly customizable, and you can set up other automated actions just like it.
''') + '\n\n' + __('''
Maybe you want to set a higher priority on any ticket with the word urgent in the title. Maybe you want to avoid sending auto-reply emails to customers from certain organizations. Maybe you want mark a ticket as pending whenever someone adds an internal note to a ticket.
''') + '\n\n' + __('''
Whatever it is, you can do it with triggers: actions that watch tickets for certain changes, and then fire off whenever those changes occur.
''')

View file

@ -9,28 +9,38 @@ module Translation::SynchronizesFromPo
def sync
Locale.to_sync.each do |locale|
ActiveRecord::Base.transaction do
sync_locale_from_po locale.locale
end
end
end
def sync_locale_from_po(locale) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
def sync_locale_from_po(locale) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
previous_unmodified_translations = Translation.where(locale: locale, is_synchronized_from_codebase: true).select { |t| t.target.eql?(t.target_initial) }
updated_translation_ids = Set[]
importable_translations = []
strings_for_locale(locale).each_pair do |source, entry| # rubocop:disable Metrics/BlockLength
if source.length > 500 || entry.translation.length > 500
Rails.logger.error "Cannot import translation for locale #{locale} because it exceeds maximum string length of 500: source: '#{source}', translation: '#{entry.translation}'"
next
end
strings_for_locale(locale).each_pair do |source, entry|
t = Translation.find_source(locale, source)
# New string
if !t
Translation.new(
importable_translations << Translation.new(
locale: locale,
source: source,
target: entry.translation,
target_initial: entry.translation,
is_synchronized_from_codebase: true,
synchronized_from_translation_file: entry.translation_file,
created_by_id: 1,
updated_by_id: 1
).save!
)
next
end
@ -48,6 +58,8 @@ module Translation::SynchronizesFromPo
end
updated_translation_ids.add t.id
end
Translation.import importable_translations
# Remove any unmodified & synchronized strings that are not present in the data any more.
previous_unmodified_translations.reject { |t| updated_translation_ids.member? t.id }.each(&:destroy!)
true

View file

@ -245,7 +245,7 @@ msgid "** Data Privacy **, helps you to delete and verify the removal of existin
msgstr ""
#: app/assets/javascripts/app/models/sla.coffee
msgid "** Service Level Agreements **, abbreviated ** SLAs **, help you to meet certain customers' time-related responses. Thus, for example, you can say customers should always get a response from you after 8 hours at the latest. In the event of an imminent violation or a breach, Zammad will alert you to such events.\n\nIt can be ** response time ** (time between the creation of a ticket and the first reaction of an agent), ** update time ** (time between a customer's request and an agent's reaction) and ** solution time ** (time between creation and closing a ticket ) To be defined.\n\nAny violations are displayed in a separate view in the overviews. You can also configure ** e-mail notifications **."
msgid "** Service Level Agreements **, abbreviated ** SLAs **, help you to meet certain customers' time-related responses. Thus, for example, you can say customers should always get a response from you after 8 hours at the latest. In the event of an imminent violation or a breach, Zammad will alert you to such events."
msgstr ""
#: app/assets/javascripts/app/controllers/_plugin/keyboard_shortcuts.coffee
@ -793,6 +793,10 @@ msgstr ""
msgid "Any Recipient"
msgstr ""
#: app/assets/javascripts/app/models/sla.coffee
msgid "Any violations are displayed in a separate view in the overviews. You can also configure ** e-mail notifications **."
msgstr ""
#: db/seeds/settings.rb
msgid "App ID"
msgstr ""
@ -1074,6 +1078,10 @@ msgstr ""
msgid "Available for the following roles"
msgstr ""
#: app/assets/javascripts/app/models/text_module.coffee
msgid "Available objects are:\n* ticket (e. g. ticket.state, ticket.group)\n* ticket.customer (e. g. ticket.customer.firstname, ticket.customer.lastname)\n* ticket.owner (e. g. ticket.owner.firstname, ticket.owner.lastname)\n* ticket.organization (e. g. ticket.organization.name)\n* user (e. g. user.firstname, user.email)"
msgstr ""
#: db/seeds/settings.rb
msgid "Available types for a new ticket"
msgstr ""
@ -2077,7 +2085,7 @@ msgid "Create Text Modules"
msgstr ""
#: app/assets/javascripts/app/models/text_module.coffee
msgid "Create Text Modules to **spend less time writing responses**. Text Modules can include smart variables like the users name or email address.\n\nExamples of snippets are:\n\n* Hello Mrs. #{ticket.customer.lastname},\n* Hello Mr. #{ticket.customer.lastname},\n* Hello #{ticket.customer.firstname},\n* My Name is #{user.firstname},\n\nOf course you can also use multi line snippets.\n\nAvailable objects are:\n* ticket (e. g. ticket.state, ticket.group)\n* ticket.customer (e. g. ticket.customer.firstname, ticket.customer.lastname)\n* ticket.owner (e. g. ticket.owner.firstname, ticket.owner.lastname)\n* ticket.organization (e. g. ticket.organization.name)\n* user (e. g. user.firstname, user.email)\n\nTo select placeholders from a list, just enter \"::\".\n"
msgid "Create Text Modules to **spend less time writing responses**. Text Modules can include smart variables like the users name or email address."
msgstr ""
#: app/controllers/first_steps_controller.rb
@ -3737,7 +3745,7 @@ msgid "Every category in your knowledge base should be given a unique icon for m
msgstr ""
#: app/assets/javascripts/app/models/trigger.coffee
msgid "Every time a customer creates a new ticket, they automatically receive a confirmation email to assure them that their issue has been submitted successfully. This behavior is built into Zammad, but its also highly customizable, and you can set up other automated actions just like it.\n\nMaybe you want to set a higher priority on any ticket with the word “urgent” in the title. Maybe you want to avoid sending auto-reply emails to customers from certain organizations. Maybe you want mark a ticket as “pending” whenever someone adds an internal note to a ticket.\n\nWhatever it is, you can do it with triggers: actions that watch tickets for certain changes, and then fire off whenever those changes occur."
msgid "Every time a customer creates a new ticket, they automatically receive a confirmation email to assure them that their issue has been submitted successfully. This behavior is built into Zammad, but its also highly customizable, and you can set up other automated actions just like it."
msgstr ""
#: app/assets/javascripts/app/views/api.jst.eco
@ -3757,6 +3765,10 @@ msgstr ""
msgid "Examples"
msgstr ""
#: app/assets/javascripts/app/models/text_module.coffee
msgid "Examples of snippets are:\n* Hello Mrs. #{ticket.customer.lastname},\n* Hello Mr. #{ticket.customer.lastname},\n* Hello #{ticket.customer.firstname},\n* My Name is #{user.firstname},"
msgstr ""
#: app/assets/javascripts/app/controllers/_manage/ticket_auto_assignment.coffee
msgid "Exception users"
msgstr ""
@ -5126,6 +5138,10 @@ msgstr ""
msgid "Ionicons"
msgstr ""
#: app/assets/javascripts/app/models/sla.coffee
msgid "It can be ** response time ** (time between the creation of a ticket and the first reaction of an agent), ** update time ** (time between a customer's request and an agent's reaction) and ** solution time ** (time between creation and closing a ticket ) To be defined."
msgstr ""
#: app/assets/javascripts/app/controllers/ticket_overview.coffee
msgid "Items per page"
msgstr ""
@ -5665,6 +5681,10 @@ msgstr ""
msgid "May"
msgstr ""
#: app/assets/javascripts/app/models/trigger.coffee
msgid "Maybe you want to set a higher priority on any ticket with the word “urgent” in the title. Maybe you want to avoid sending auto-reply emails to customers from certain organizations. Maybe you want mark a ticket as “pending” whenever someone adds an internal note to a ticket."
msgstr ""
#: app/assets/javascripts/app/views/layout_ref/organization_profile.jst.eco
#: app/assets/javascripts/app/views/organization_profile/object.jst.eco
#: app/assets/javascripts/app/views/popover/organization.jst.eco
@ -6673,6 +6693,10 @@ msgstr ""
msgid "October"
msgstr ""
#: app/assets/javascripts/app/models/text_module.coffee
msgid "Of course you can also use multi line snippets."
msgstr ""
#: app/assets/javascripts/app/controllers/_profile/linked_accounts.coffee
#: db/seeds/settings.rb
msgid "Office 365"
@ -10340,6 +10364,10 @@ msgstr ""
msgid "What values of %s should be synced to users."
msgstr ""
#: app/assets/javascripts/app/models/trigger.coffee
msgid "Whatever it is, you can do it with triggers: actions that watch tickets for certain changes, and then fire off whenever those changes occur."
msgstr ""
#: app/assets/javascripts/app/controllers/_integration/slack.coffee
msgid "When notification is being sent."
msgstr ""

View file

@ -15,6 +15,14 @@ class Generators::TranslationCatalog::Extractor::Base
end
end
def validate_strings
@strings.to_a.each do |s|
if s.length > 500
raise "Found a string that longer than than the allowed 500 characters: '#{s}'"
end
end
end
def extract_from_string(string, filename)
raise NotImplementedError
end

View file

@ -19,6 +19,7 @@ class Generators::TranslationCatalog::Extractor::Erb < Generators::TranslationCa
references[result] << filename
end
end
validate_strings
end
def find_files(base_path)

View file

@ -29,6 +29,7 @@ class Generators::TranslationCatalog::Extractor::Frontend < Generators::Translat
references[result] << filename
end
end
validate_strings
end
def find_files(base_path)

View file

@ -24,6 +24,7 @@ class Generators::TranslationCatalog::Extractor::Ruby < Generators::TranslationC
references[result] << filename
end
end
validate_strings
end
def find_files(base_path)

View file

@ -40,4 +40,16 @@ RSpec.describe Generators::TranslationCatalog::Extractor::Erb do
expect(result_strings).to eq(Set[])
end
end
context 'with strings too long' do
let(:string) do
<<~"CODE"
<%= t("#{'a' * 501}") %>
CODE
end
it 'raises an error' do
expect { result_strings }.to raise_error(%r{Found a string that longer than than the allowed 500 characters})
end
end
end

View file

@ -42,4 +42,16 @@ RSpec.describe Generators::TranslationCatalog::Extractor::Frontend do
expect(result_strings).to eq(Set[])
end
end
context 'with strings too long' do
let(:string) do
<<~"CODE"
__("#{'a' * 501}")
CODE
end
it 'raises an error' do
expect { result_strings }.to raise_error(%r{Found a string that longer than than the allowed 500 characters})
end
end
end

View file

@ -41,4 +41,16 @@ RSpec.describe Generators::TranslationCatalog::Extractor::Ruby do
expect(result_strings).to eq(Set[])
end
end
context 'with strings too long' do
let(:string) do
<<~"CODE"
__("#{'a' * 501}")
CODE
end
it 'raises an error' do
expect { result_strings }.to raise_error(%r{Found a string that longer than than the allowed 500 characters})
end
end
end

View file

@ -177,6 +177,9 @@ RSpec.describe Translation do
msgid "custom-string-translated"
msgstr "custom-string-übersetzt"
msgid "custom-string-too-long"
msgstr "custom-string-too-long #{'a' * 501}"
msgid "custom-string-untranslated"
msgstr ""
@ -221,6 +224,10 @@ RSpec.describe Translation do
it 'adds the custom fuzzy entry without content' do
expect(described_class.find_source('de-de', 'custom-string-fuzzy')).to have_attributes(target: '')
end
it 'ignores strings that are too long' do
expect(described_class.find_source('de-de', 'custom-string-too-long')).to be_nil
end
end
end