Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Email templates in multiple languages #82

Closed
roiez opened this issue Apr 7, 2016 · 12 comments
Closed

Email templates in multiple languages #82

roiez opened this issue Apr 7, 2016 · 12 comments

Comments

@roiez
Copy link

roiez commented Apr 7, 2016

Hi,
this is my CultureInfo table:

1   635955378572137575  en  English English
2   635955378643707575  es  español    Spanish
3   635955378646417575  de  Deutsch German
4   635955378648517575  da  dansk   Danish
5   635955378650277575  fr  français   French
6   635955378651867575  sv  svenska Swedish
7   635955378653517575  it  italiano    Italian
8   635955378655217575  pt  Português  Portuguese
9   635955378656707575  tr  Türkçe    Turkish
10  635955378658297575  nl  Nederlands  Dutch
11  635955378659837575  pl  polski  Polish
12  635955378661407575  no  norsk   Norwegian
13  635955378663227575  ro  română    Romanian
14  635955378664837575  zh  中文  Chinese
15  635955378666407575  fi  suomi   Finnish
16  635955378668057575  id  Bahasa Indonesia    Indonesian
17  635955378670167575  ko  한국어   Korean
18  635955378671887575  ar  العربية  Arabic
19  635955378673557575  lv  latviešu   Latvian
20  635955378682787575  ru  русский  Russian
21  635955378688657575  el  Ελληνικά    Greek

I need to generate email messages in all these languages. The following code creates English messages only, for all the cultures

                SystemEmailLogic.RegisterSystemEmail(() => new EmailTemplateEntity
                {
                    Messages = CultureInfoLogic.ForEachCulture(culture => new         EmailTemplateMessageEntity(culture)
                    {
                        Text = PoiBEmailMessage.MessageBody.NiceToString(),
                        Subject = PoiBEmailMessage.MessageSubject.NiceToString()
                    }).ToMList()
                });

what do I need to do for all other languages?

@olmobrutall
Copy link
Collaborator

It should generate an email template with all this messages. Can you make a breakpoint inside ForEachCulture?

A different thing is if all the messages are similar. This will require you to translate PoiBEmailMessage but this does not make sense for applications, only for modules that will be distributed (like Signum extensions)

@zeevir
Copy link

zeevir commented Apr 8, 2016

Olmo this is @roiez, from my private account,
I understand.
We have the body of PoiBEmail translated to all target languages.
What I am missing is the next step,
what should I do to accomplish the behavior of ResetPassword,
when you generate a new environment, you are requested to create a ResetPassword email in a number of languages, in our case, I need to have the same for PoiBEmail.

@olmobrutall
Copy link
Collaborator

The way this works is by using the build-in localization system in Signum.Framework that reads the .xml files in Translations folder of Signum.Entities Signum.Entities.Extensions or YourApp.Entities.

You can also start the Translation module of Signum.Extensions to generate/synchronize this translations using bing/google and provide a UI for translators.

That said, if you assume that the right template text is in the source code you loose the posibility to change it in real time on LIVE environment. We have settled on letting the DB be responsible of the templates, not the source code, to avoid duplication.

In this case I'll go for generating the environment with simplified English-only templates.

@roiez
Copy link
Author

roiez commented Apr 10, 2016

OK, I created xml translation files for each language and now I am able to generate messages in all target languages.
However I run into a new problem. I am creating my emails programmatically and the problem is that in spite of having translations loaded into database, the email view always shows an English message.
How do I make sure the culture of EmailOwner will be reflected in the email view?

@olmobrutall
Copy link
Collaborator

  • The EmailOwner should points to a valid CultureInfo
  • You should have the EmailOwner in the To field as a QueryToken.

If still doesn't work, then is a bug :D

@roiez
Copy link
Author

roiez commented Apr 11, 2016

I made sure EmailOwner points to a culture that is 100% translated and is present in the database, and the To field is populated by that EmailOwner, indeed there was a problem, now the correct translation IS being rendered, however I get an exception after the email is sent: "Type AccountEntity is not in the list of ImplementedBy: UserEntity -> EmailOwnerID_User".
My EmailOwner is Account:

   public static Expression> EmailOwnerDataExpression = a =>
            new EmailOwnerData
            {
                Owner = a.ToLite(),
                CultureInfo = CultureInfo.GetCultureInfo(a.Language).ToCultureInfoEntity(),                
                DisplayName = a.UserName,
                Email = a.Email,
            };
        [ExpressionField]
        public EmailOwnerData EmailOwnerData => EmailOwnerDataExpression.Evaluate(this);

P.S. Further more, I have a problem with non Latin languages, they look like this: "????????, ????."

@olmobrutall
Copy link
Collaborator

The ImplementedBy problem is in your Starter.cs. There is some OverrideAttributes that change the implementations for EmailMessageEntity.Recipients including UserEntity but not AccountEntity.

About the encoding, I've no idea, you'll need to debug it yourself why the emails are not sent with the right encoding. Could be a DB thing but most probably is n the SMTP part. If you don't find it we can take a look some evening or on Sunday.

@roiez
Copy link
Author

roiez commented Apr 11, 2016

When I do this:

sb.Schema.Settings.FieldAttributes((EmailMessageEntity em) => em.Recipients.First().EmailOwner).Replace(new ImplementedByAttribute(typeof(UserEntity), typeof(AccountEntity)));
 

I get this error:

 
AccountEntity is already included in the Schema
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 
Exception Details: System.InvalidOperationException: AccountEntity is already included in the Schema
Source Error: 
Line 44:                 if (schema.Tables.ContainsKey(t))
Line 45:                     throw new InvalidOperationException("{0} is already included in the Schema".FormatWith(t.TypeName()));
Line 46:             };
Line 47:         }
Line 48: 
Source File: C:\work\Projects\BackOffice\Framework\Signum.Engine\Schema\SchemaBuilder\SchemaBuilder.cs    Line: 46 
Stack Trace: 
[InvalidOperationException: AccountEntity is already included in the Schema]
   Signum.Engine.Maps.SchemaBuilder.<.ctor>b__3_2(Type t) in C:\work\Projects\BackOffice\Framework\Signum.Engine\Schema\SchemaBuilder\SchemaBuilder.cs:46
   Signum.Entities.MixinDeclarations.Register(Type mainEntity, Type mixinEntity) in C:\work\Projects\BackOffice\Framework\Signum.Entities\MixinEntity.cs:75
   Signum.Entities.MixinDeclarations.Register() in C:\work\Projects\BackOffice\Framework\Signum.Entities\MixinEntity.cs:61
   BackOffice.Logic.Starter.Start(String connectionString) in C:\work\Projects\BackOffice\BackOffice.Logic\Starter.cs:121
   BackOffice.Web.MvcApplication.Application_Start() in C:\work\Projects\BackOffice\BackOffice.Web\Global.asax.cs:152
[HttpException (0x80004005): AccountEntity is already included in the Schema]
   System.Web.HttpApplicationFactory.EnsureAppStartCalledForIntegratedMode(HttpContext context, HttpApplication app) +544
   System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) +186
   System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context) +172
   System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +402
   System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +343
[HttpException (0x80004005): AccountEntity is already included in the Schema]
   System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +579
   System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +112
   System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +712

It appears that the basic mixing is responsible for this error:

MixinDeclarations.Register();

Removing it allows to override EmailMessageEntity.Recipients, but then I am loosing my createdby etc. fields.

@olmobrutall
Copy link
Collaborator

The MixinDeclarations.Register should happen at the very beginning of the Starter.Start method, looks like it's happening to late.

@roiez
Copy link
Author

roiez commented Apr 11, 2016

Olmo thank you very much! This fixed the issue.

@roiez roiez closed this as completed Apr 12, 2016
@roiez
Copy link
Author

roiez commented Jun 20, 2016

Hi Olmo and the community,
after a long pause, we are back to emails. The problem we are experiencing is with translated emails as follows: the messages are always in English and the issue seems to lay with this code of the framework:

public static IEnumerable CreateEmailMessage(this ISystemEmail systemEmail)
        {
            if (systemEmail.UntypedEntity == null)
                throw new InvalidOperationException("Entity property not set on SystemEmail");
            using (IsolationEntity.Override(systemEmail.UntypedEntity.TryIsolation()))
            {
                var systemEmailEntity = ToSystemEmailEntity(systemEmail.GetType());
                var template = GetDefaultTemplate(systemEmailEntity);
                return EmailTemplateLogic.CreateEmailMessage(template.ToLite(), systemEmail.UntypedEntity, systemEmail);
            }
        }

There seems to be no mentioning of CulterInfo at the message level.

@roiez roiez reopened this Jun 20, 2016
@olmobrutall
Copy link
Collaborator

Hi roiez,

Nice to see you back.

The culture info is selected from the recipients, determined in the template.

If you take a look to GetEmailMessageInternal in https://github.com/signumsoftware/extensions/blob/master/Signum.Engine.Extensions/Mailing/EmailTemplateRenderer.cs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants