From: Rogan Hamby Date: Wed, 23 Feb 2022 18:55:01 +0000 (-0500) Subject: This feature supplies the ability to create alternate templates for Action Triggers X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=c318a31d41ab2c9dedc05cc18e64c1d9f7c6ca89;p=evergreen%2Fpines.git This feature supplies the ability to create alternate templates for Action Triggers that will generate locale specific out for Action Triggers. If you send notices in multiple languages, we recommend putting some words to that effect in your notice templates. The template, message and message title can all be localized. To use the feature the following new UI elements have been added: - When you double-click on an Event Definition under Notifications / Action Triggers to edit it there will be a tab option for Edit Alternate Template if the reactor is ProcessTemplate, SendEmail or SendSMS. - In the Patron Registration and Patron Editor screens staff members may now select a locale for a patron and edit it in the Patron Preferred Language field. - Patrons may set their own locale in the My Account interface off the OPAC by going to Preferences -> Personal Information and setting the Preferred Language field. The templates used on the Edit Definition tab are the defaults that are used if there are no alternate templates available that match the preferred language. If alternate templates are available the system will use a locale that is an exact match and then if failing that use one where the language code matches and then fall back to the default one. For example, if a patron has a locale of fr-CA and there are templates for both fr-CA and fr-FR it will use the fr-CA. If the fr-CA template was deleted it would fall back on using the fr-FR for the patron since it at least shares the same base language. Valid locales are the codes defined in the i18n_locale table in the config schema. Signed-off-by: Mike Rylander Signed-off-by: Jane Sandberg --- diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml index e3bdba88d4..92abe1547d 100644 --- a/Open-ILS/examples/fm_IDL.xml +++ b/Open-ILS/examples/fm_IDL.xml @@ -1333,6 +1333,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + @@ -1508,6 +1509,39 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -4118,6 +4152,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + @@ -4152,6 +4187,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/triggers/trigger-edit.component.html b/Open-ILS/src/eg2/src/app/staff/admin/local/triggers/trigger-edit.component.html index cee99871d6..34a66a86be 100644 --- a/Open-ILS/src/eg2/src/app/staff/admin/local/triggers/trigger-edit.component.html +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/triggers/trigger-edit.component.html @@ -23,7 +23,35 @@
- + + +
  • + Edit Alternate Template + + + + +

    Alternate Templates

    + + + + + + +
  • Edit Environment diff --git a/Open-ILS/src/eg2/src/app/staff/admin/local/triggers/trigger-edit.component.ts b/Open-ILS/src/eg2/src/app/staff/admin/local/triggers/trigger-edit.component.ts index 9b665b627a..f41dc028d0 100644 --- a/Open-ILS/src/eg2/src/app/staff/admin/local/triggers/trigger-edit.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/admin/local/triggers/trigger-edit.component.ts @@ -21,22 +21,27 @@ export class EditEventDefinitionComponent implements OnInit { evtDefId: number; evtDefName: String; + evtReactor: string; + evtAltEligible: Boolean = false; testErr1: String = ''; testErr2: String = ''; testResult: String = ''; testDone: Boolean = false; + altTemplateDataSource: GridDataSource = new GridDataSource(); envDataSource: GridDataSource = new GridDataSource(); paramDataSource: GridDataSource = new GridDataSource(); - editTab: 'def' | 'env' | 'param' | 'test' = 'def'; + editTab: 'def' | 'alt' | 'env' | 'param' | 'test' = 'def'; @ViewChild('paramDialog') paramDialog: FmRecordEditorComponent; @ViewChild('envDialog') envDialog: FmRecordEditorComponent; + @ViewChild('altTemplateDialog') altTemplateDialog: FmRecordEditorComponent; @ViewChild('envGrid') envGrid: GridComponent; @ViewChild('paramGrid') paramGrid: GridComponent; + @ViewChild('altTemplateGrid') altTemplateGrid: GridComponent; @ViewChild('updateSuccessString') updateSuccessString: StringComponent; @ViewChild('updateFailedString') updateFailedString: StringComponent; @@ -69,11 +74,24 @@ export class EditEventDefinitionComponent implements OnInit { this.evtDefName = rec.name(); }); + // get current event def reactor to decide if the alt template tab should show + this.pcrud.search('atevdef', + {id: this.evtDefId}, {}).toPromise().then(rec => { + this.evtReactor = rec.reactor(); + if ('ProcessTemplate SendEmail SendSMS'.indexOf(this.evtReactor) > -1) + { this.evtAltEligible = true; } + }); + this.envDataSource.getRows = (pager: Pager, sort: any[]) => { return this.pcrud.search('atenv', {event_def: this.evtDefId}, {}); }; + this.altTemplateDataSource.getRows = (pager: Pager, sort: any[]) => { + return this.pcrud.search('atevalt', + {event_def: this.evtDefId}, {}); + }; + this.paramDataSource.getRows = (pager: Pager, sort: any[]) => { return this.pcrud.search('atevparam', {event_def: this.evtDefId}, {}); @@ -88,6 +106,10 @@ export class EditEventDefinitionComponent implements OnInit { this.createNewThing(this.envDialog, this.envGrid, 'atenv'); } + createNewAltTemplate = () => { + this.createNewThing(this.altTemplateDialog, this.altTemplateGrid, 'atevalt'); + } + createNewParam = () => { this.createNewThing(this.paramDialog, this.paramGrid, 'atevparam'); } @@ -118,6 +140,8 @@ export class EditEventDefinitionComponent implements OnInit { let currentGrid; if (idlThings[0].classname === 'atenv') { currentGrid = this.envGrid; + } else if (idlThings[0].classname === 'atevalt') { + currentGrid = this.altTemplateGrid; } else { currentGrid = this.paramGrid; } @@ -157,6 +181,9 @@ export class EditEventDefinitionComponent implements OnInit { if (selectedRecord.classname === 'atenv') { currentDialog = this.envDialog; currentGrid = this.envGrid; + } else if (selectedRecord.classname === 'atevalt') { + currentDialog = this.altTemplateDialog; + currentGrid = this.altTemplateGrid; } else { currentDialog = this.paramDialog; currentGrid = this.paramGrid; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm index faf723b659..c0d9851f02 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm @@ -1654,6 +1654,20 @@ __PACKAGE__->register_method( } ); +__PACKAGE__->register_method( + method => "update_passwd", + api_name => "open-ils.actor.user.locale.update", + signature => { + desc => "Update the operator's i18n locale", + params => [ + { desc => 'Authentication token', type => 'string' }, + { desc => 'New locale', type => 'string' }, + { desc => 'Current password', type => 'string' } + ], + return => {desc => '1 on success, Event on error or incorrect current password'} + } +); + sub update_passwd { my( $self, $conn, $auth, $new_val, $orig_pw ) = @_; my $e = new_editor(xact=>1, authtoken=>$auth); @@ -1696,6 +1710,10 @@ sub update_passwd { } elsif( $api =~ /email/o ) { $db_user->email($new_val); $at_event++; + + } elsif( $api =~ /locale/o ) { + $db_user->locale($new_val); + $at_event++; } } diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Event.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Event.pm index 419bd7f458..bd068e56c5 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Event.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Event.pm @@ -492,6 +492,57 @@ sub build_environment { $self->environment->{usr_message}{title} = $self->event->event_def->message_title; $self->environment->{user_data} = $self->user_data; + my ($usr_locale, $alt_templates, $query, $query_result, $new_template_id); + my $reactor = $self->environment->{event}->event_def->reactor; + $query = { + select => { atevalt => ['id', 'locale'] }, + from => 'atevalt', + where => { + event_def => $self->environment->{event}->event_def->id, + active => 't' + } + }; + my $e = new_editor(xact=>1); + if ($reactor) { + if ( $reactor eq 'SendEmail' + or $reactor eq 'ProcessTemplate' + or $reactor eq 'SendSMS') { + $query_result = $e->json_query($query); + $alt_templates = $query_result; + $query = { + select => { au => ['locale'] }, + from => 'au', + where => { id => $self->environment->{event}->target } + }; + $query_result = $e->json_query($query); + $usr_locale = @$query_result[0]->{locale}; + if ($alt_templates and @$alt_templates and $usr_locale) { + foreach (@$alt_templates) { + if ($_->{locale} eq $usr_locale) { + $new_template_id = $_->{id}; + $self->environment->{tt_locale} = $_->{locale}; + last; + } else { #attempt a lanuage if not locale match + if ((split /\p{Dash}/,$_->{locale})[0] eq (split /\p{Dash}/,$usr_locale)[0]) { + $new_template_id = $_->{id}; + $self->environment->{tt_locale} = $_->{locale}; + } + } + } + } + if ($new_template_id) { + $query = { + select => { atevalt => ['template','message_template','message_title'] }, + from => 'atevalt', + where => { id => $new_template_id } + }; + $query_result = $e->json_query($query); + $self->environment->{template} = @$query_result[0]->{template}; + $self->environment->{usr_message}{template} = @$query_result[0]->{message_template}; + $self->environment->{usr_message}{title} = @$query_result[0]->{message_title}; + } + } + } $current_environment = $self->environment; $self->environment->{params}{ $_->param } = $compartment->reval($_->value) for ( @{$self->event->event_def->params} ); diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Reactor.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Reactor.pm index cb7d5b818d..74255e4609 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Reactor.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Trigger/Reactor.pm @@ -553,6 +553,7 @@ sub run_TT { my $t_o = Fieldmapper::action_trigger::event_output->new; $t_o->data( ($error) ? $error : $output ); $t_o->is_error( ($error) ? 't' : 'f' ); + $t_o->locale($env->{tt_locale}); $logger->info("trigger: writing " . length($t_o->data) . " bytes to template output"); $env->{EventProcessor}->editor->xact_begin; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm index 6d5432eced..0f8557b142 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm @@ -268,6 +268,7 @@ sub load { return $self->load_myopac_update_email if $path =~ m|opac/myopac/update_email|; return $self->load_myopac_update_password if $path =~ m|opac/myopac/update_password|; return $self->load_myopac_update_username if $path =~ m|opac/myopac/update_username|; + return $self->load_myopac_update_locale if $path =~ m|opac/myopac/update_locale|; return $self->load_myopac_bookbags if $path =~ m|opac/myopac/lists|; return $self->load_myopac_bookbag_print if $path =~ m|opac/myopac/list/print|; return $self->load_myopac_bookbag_update if $path =~ m|opac/myopac/list/update|; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm index 084aecccd5..dcc2f1403e 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Account.pm @@ -37,7 +37,7 @@ sub prepare_extended_user_info { { flesh => 2, flesh_fields => { - au => [qw/card home_ou addresses ident_type billing_address waiver_entries/, @extra_flesh], + au => [qw/card home_ou addresses ident_type locale billing_address waiver_entries/, @extra_flesh], "aou" => ["billing_address"] } } @@ -2766,6 +2766,46 @@ sub load_myopac_update_username { return $self->generic_redirect($url); } +sub load_myopac_update_locale { + my $self = shift; + my $e = $self->editor; + my $ctx = $self->ctx; + my $lang = $self->cgi->param('pref_lang') || ''; + my $current_pw = $self->cgi->param('current_pw') || ''; + + $self->prepare_extended_user_info; + + my $locs = $U->simplereq( + 'open-ils.cstore', + "open-ils.cstore.direct.config.i18n_locale.search.atomic", + { "code" => { "!=" => undef } } + ); + + my %user_locales; + foreach my $l (@$locs) { $user_locales{$l->code} = $l->name; } + $self->ctx->{i18n_locales} = \%user_locales; + + return Apache2::Const::OK + unless $self->cgi->request_method eq 'POST'; + + if($lang ne $e->requestor->locale) { + my $evt = $U->simplereq( + 'open-ils.actor', + 'open-ils.actor.user.locale.update', + $e->authtoken, $lang, $current_pw); + + if($U->event_equals($evt, 'INCORRECT_PASSWORD')) { + $ctx->{password_incorrect} = 1; + return Apache2::Const::OK; + } + } + + my $url = $self->apache->unparsed_uri; + $url =~ s/update_locale/prefs/; + + return $self->generic_redirect($url); +} + sub load_myopac_update_password { my $self = shift; my $e = $self->editor; diff --git a/Open-ILS/src/sql/Pg/005.schema.actors.sql b/Open-ILS/src/sql/Pg/005.schema.actors.sql index 9a42e05427..b18a33cf6f 100644 --- a/Open-ILS/src/sql/Pg/005.schema.actors.sql +++ b/Open-ILS/src/sql/Pg/005.schema.actors.sql @@ -71,7 +71,8 @@ CREATE TABLE actor.usr ( create_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), expire_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT (now() + '3 years'::INTERVAL), claims_never_checked_out_count INT NOT NULL DEFAULT 0, - last_update_time TIMESTAMP WITH TIME ZONE + last_update_time TIMESTAMP WITH TIME ZONE, + locale TEXT REFERENCES config.i18n_locale(code) INITIALLY DEFERRED ); COMMENT ON TABLE actor.usr IS $$ User objects diff --git a/Open-ILS/src/sql/Pg/400.schema.action_trigger.sql b/Open-ILS/src/sql/Pg/400.schema.action_trigger.sql index 3a0816a07c..05a9af9501 100644 --- a/Open-ILS/src/sql/Pg/400.schema.action_trigger.sql +++ b/Open-ILS/src/sql/Pg/400.schema.action_trigger.sql @@ -212,6 +212,17 @@ CREATE TABLE action_trigger.event_definition ( CONSTRAINT ev_def_name_owner_once UNIQUE (owner, name) ); +CREATE TABLE action_trigger.alternate_template ( + id SERIAL, + event_def INTEGER REFERENCES action_trigger.event_definition(id) INITIALLY DEFERRED, + template TEXT, + active BOOLEAN DEFAULT TRUE, + locale TEXT REFERENCES config.i18n_locale(code) INITIALLY DEFERRED, + message_title TEXT, + message_template TEXT, + UNIQUE (event_def,locale) +); + CREATE OR REPLACE FUNCTION action_trigger.check_valid_retention_interval() RETURNS TRIGGER AS $_$ BEGIN @@ -263,7 +274,8 @@ CREATE TABLE action_trigger.event_output ( id BIGSERIAL PRIMARY KEY, create_time TIMESTAMPTZ NOT NULL DEFAULT NOW(), is_error BOOLEAN NOT NULL DEFAULT FALSE, - data TEXT NOT NULL + data TEXT NOT NULL, + locale TEXT ); CREATE TABLE action_trigger.event ( diff --git a/Open-ILS/src/sql/Pg/upgrade/xxxx.schema.preferred_locale_and_alternate_at_templates.sql b/Open-ILS/src/sql/Pg/upgrade/xxxx.schema.preferred_locale_and_alternate_at_templates.sql new file mode 100644 index 0000000000..d70fd2fbca --- /dev/null +++ b/Open-ILS/src/sql/Pg/upgrade/xxxx.schema.preferred_locale_and_alternate_at_templates.sql @@ -0,0 +1,20 @@ +BEGIN; + +SELECT evergreen.upgrade_deps_block_check('xxxx', :eg_version); + +CREATE TABLE action_trigger.alternate_template ( + id SERIAL, + event_def INTEGER REFERENCES action_trigger.event_definition(id) INITIALLY DEFERRED, + template TEXT, + active BOOLEAN DEFAULT TRUE, + message_title TEXT, + message_template TEXT, + locale TEXT REFERENCES config.i18n_locale(code) INITIALLY DEFERRED, + UNIQUE (event_def,locale) +); + +ALTER TABLE actor.usr ADD COLUMN locale TEXT REFERENCES config.i18n_locale(code) INITIALLY DEFERRED; + +ALTER TABLE action_trigger.event_output ADD COLUMN locale TEXT; + +COMMIT; diff --git a/Open-ILS/src/templates-bootstrap/opac/css/style.css.tt2 b/Open-ILS/src/templates-bootstrap/opac/css/style.css.tt2 index a40c8eb28b..49a989d8ff 100755 --- a/Open-ILS/src/templates-bootstrap/opac/css/style.css.tt2 +++ b/Open-ILS/src/templates-bootstrap/opac/css/style.css.tt2 @@ -373,6 +373,10 @@ Novelist Styling max-width: 100px !important; } +.mod-control{ + max-width: 150px !important; +} + .card-body:empty{ display:none; } diff --git a/Open-ILS/src/templates-bootstrap/opac/myopac/prefs.tt2 b/Open-ILS/src/templates-bootstrap/opac/myopac/prefs.tt2 index bf9f1169a7..74bb68c5c1 100755 --- a/Open-ILS/src/templates-bootstrap/opac/myopac/prefs.tt2 +++ b/Open-ILS/src/templates-bootstrap/opac/myopac/prefs.tt2 @@ -116,6 +116,15 @@ + [% l("Preferred Language") %] + [% ctx.user.locale.name | html %] + + [% l('Change') %] + + + + [% l("Home Library") %] [% ctx.get_aou(ctx.user.home_ou.parent_ou).name %]
    diff --git a/Open-ILS/src/templates-bootstrap/opac/myopac/update_locale.tt2 b/Open-ILS/src/templates-bootstrap/opac/myopac/update_locale.tt2 new file mode 100755 index 0000000000..b09f1a0da6 --- /dev/null +++ b/Open-ILS/src/templates-bootstrap/opac/myopac/update_locale.tt2 @@ -0,0 +1,38 @@ +[% PROCESS "opac/parts/header.tt2"; + PROCESS "opac/parts/misc_util.tt2"; + WRAPPER "opac/parts/myopac/base.tt2"; + myopac_page = "prefs" %] +

    [% l('Update Preferred Language') %]

    +
    + +
    + [% l('Update Preferred Language') %] +
    + +[% IF ctx.password_incorrect %] +
    + [% |l %]Your current password was not correct.[% END %] +
    +[% END %] + +
    + [% IF CGI.param("return_to_referer") %] + + [% END %] + + + + + + +
    [% l('Current Preferred Language') %][% ctx.user.locale.name | html %]
    [% l('Current Password') %]
    [% l('New Preferred Language') %] + +
    + +
    + +[% END %] diff --git a/Open-ILS/src/templates/staff/circ/patron/t_edit.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_edit.tt2 index e9a166bb71..ebafd0829f 100644 --- a/Open-ILS/src/templates/staff/circ/patron/t_edit.tt2 +++ b/Open-ILS/src/templates/staff/circ/patron/t_edit.tt2 @@ -479,6 +479,20 @@ within the "form" by name for validation.
    + +
    + [% draw_field_label('au', 'locale') %] +
    + +
    +
    +
    [% draw_field_label('au', 'email') %] diff --git a/Open-ILS/src/templates/staff/circ/patron/t_summary.tt2 b/Open-ILS/src/templates/staff/circ/patron/t_summary.tt2 index af98a6698b..af63520637 100644 --- a/Open-ILS/src/templates/staff/circ/patron/t_summary.tt2 +++ b/Open-ILS/src/templates/staff/circ/patron/t_summary.tt2 @@ -150,6 +150,10 @@
    {{patron().ident_value2()}}
    +
    [% l('Pref Language') %] 
    +
    {{patron().locale().name()}}
    +
    +
    [% l('Legal Name') %]
    [% l('[_1] [_2], [_3] [_4] [_5]', diff --git a/Open-ILS/web/js/ui/default/staff/circ/patron/app.js b/Open-ILS/web/js/ui/default/staff/circ/patron/app.js index 127d86cc6b..37247ef4bb 100644 --- a/Open-ILS/web/js/ui/default/staff/circ/patron/app.js +++ b/Open-ILS/web/js/ui/default/staff/circ/patron/app.js @@ -60,6 +60,7 @@ angular.module('egPatronApp', ['ngRoute', 'ui.bootstrap', 'egUserBucketMod', 'net_access_level', 'ident_type', 'ident_type2', + 'locale', 'cards', 'groups' ]); @@ -311,9 +312,15 @@ function($scope, $q , $location , $filter , egCore , egNet , egUser , egAlertDi .then(function() {return patronSvc.checkAlerts()}) .then(redirectToAlertPanel) .then(function(){ - $scope.ident_type_name = $scope.patron().ident_type().name() + if ($scope.patron().locale() !== null) { + $scope.locale_name = $scope.patron().locale().name(); + $scope.hasLocaleName = $scope.locale_name.length > 0; + } + }) + .then(function(){ + $scope.ident_type_name = $scope.patron().ident_type().name(); $scope.hasIdentTypeName = $scope.ident_type_name.length > 0; - }); + }); } else { // No patron, use the tab name as the page title. egCore.strings.setPageTitle( diff --git a/Open-ILS/web/js/ui/default/staff/circ/patron/regctl.js b/Open-ILS/web/js/ui/default/staff/circ/patron/regctl.js index ffcb7a4a0d..31bc4fe2af 100644 --- a/Open-ILS/web/js/ui/default/staff/circ/patron/regctl.js +++ b/Open-ILS/web/js/ui/default/staff/circ/patron/regctl.js @@ -21,6 +21,7 @@ angular.module('egCoreMod') stat_cats : [], stat_cat_entry_maps : {}, // cat.id to selected value virt_id : -1, // virtual ID for new objects + locales : [], init_done : false // have we loaded our initialization data? }; @@ -42,6 +43,7 @@ angular.module('egCoreMod') service.get_perm_groups(), service.get_perm_group_entries(), service.get_ident_types(), + service.get_locales(), service.get_org_settings(), service.get_stat_cats(), service.get_surveys(), @@ -49,7 +51,6 @@ angular.module('egCoreMod') ]; service.init_done = true; } - return $q.all(common_data.concat(page_data)); }; @@ -470,6 +471,19 @@ angular.module('egCoreMod') } }; + service.get_locales = function() { + if (egCore.env.i18n_l) { + service.locales = egCore.env.i18n_l.list; + return $q.when(); + } else { + return egCore.pcrud.retrieveAll('i18n_l', {}, {atomic : true}) + .then(function(locales) { + egCore.env.absorbList(locales, 'i18n_l') + service.locales = locales + }); + } + }; + service.get_net_access_levels = function() { if (egCore.env.cnal) { service.net_access_levels = egCore.env.cnal.list; @@ -771,7 +785,6 @@ angular.module('egCoreMod') service.existing_patron = current; var patron = egCore.idl.toHash(current); - patron.home_ou = egCore.org.get(patron.home_ou.id); patron.expire_date = new Date(Date.parse(patron.expire_date)); patron.dob = service.parse_dob(patron.dob); @@ -779,6 +792,7 @@ angular.module('egCoreMod') patron.net_access_level = current.net_access_level(); patron.ident_type = current.ident_type(); patron.ident_type2 = current.ident_type2(); + patron.locale = current.locale(); patron.groups = current.groups(); // pre-hash angular.forEach( @@ -907,6 +921,8 @@ angular.module('egCoreMod') user.ident_type = egCore.env.cit.map[user.ident_type]; if (user.ident_type2) user.ident_type2 = egCore.env.cit.map[user.ident_type2]; + if (user.locale) + user.locale = egCore.env.i18n_l.map[user.locale]; user.dob = service.parse_dob(user.dob); // Clear the usrname if it looks like a UUID @@ -1095,6 +1111,8 @@ angular.module('egCoreMod') patron.dob(patron.dob().toISOString().replace(/T.*/,'')); if (patron.ident_type()) patron.ident_type(patron.ident_type().id()); + if (patron.locale()) + patron.locale(patron.locale().code()); if (patron.net_access_level()) patron.net_access_level(patron.net_access_level().id()); @@ -1393,6 +1411,7 @@ function($scope , $routeParams , $q , $uibModal , $window , egCore , $scope.edit_profiles = prs.edit_profiles; $scope.edit_profile_entries = prs.edit_profile_entries; $scope.ident_types = prs.ident_types; + $scope.locales = prs.locales; $scope.net_access_levels = prs.net_access_levels; $scope.user_setting_types = prs.user_setting_types; $scope.opt_in_setting_types = prs.opt_in_setting_types; @@ -1531,6 +1550,7 @@ function($scope , $routeParams , $q , $uibModal , $window , egCore , 'au.ident_type' : 3, 'au.ident_type2' : 2, 'au.photo_url' : 2, + 'au.locale' : 2, 'au.home_ou' : 3, 'au.profile' : 3, 'au.expire_date' : 3, diff --git a/docs/RELEASE_NOTES_NEXT/Administration/localized_action_triggers.adoc b/docs/RELEASE_NOTES_NEXT/Administration/localized_action_triggers.adoc new file mode 100644 index 0000000000..0472e1fe16 --- /dev/null +++ b/docs/RELEASE_NOTES_NEXT/Administration/localized_action_triggers.adoc @@ -0,0 +1,26 @@ +== Localized Templates Available for Action Triggers == + +This feature supplies the ability to create alternate templates for Action Triggers +that will generate locale specific out for Action Triggers. If you send notices in +multiple languages, we recommend putting some words to that effect in your notice +templates. The template, message and message title can all be localized. To use the +feature the following new UI elements have been added: + +- When you double-click on an Event Definition under Notifications / Action Triggers + to edit it there will be a tab option for Edit Alternate Template if the reactor is + ProcessTemplate, SendEmail or SendSMS. +- In the Patron Registration and Patron Editor screens staff members may now select a + locale for a patron and edit it in the Patron Preferred Language field. +- Patrons may set their own locale in the My Account interface off the OPAC by going to + Preferences -> Personal Information and setting the Preferred Language field. + +The templates used on the Edit Definition tab are the defaults that are used if there are +no alternate templates available that match the preferred language. If alternate templates +are available the system will use a locale that is an exact match and then if failing that +use one where the language code matches and then fall back to the default one. + +For example, if a patron has a locale of fr-CA and there are templates for both fr-CA and +fr-FR it will use the fr-CA. If the fr-CA template was deleted it would fall back on using +the fr-FR for the patron since it at least shares the same base language. + +Valid locales are the codes defined in the i18n_locale table in the config schema.