Skip to content

MX-236: Implement i18N for the messages sent by SMS or Email#134

Open
ansh-varshney wants to merge 3 commits intoopenMF:developfrom
ansh-varshney:MX236-Implement-i18n-for-email-SMS
Open

MX-236: Implement i18N for the messages sent by SMS or Email#134
ansh-varshney wants to merge 3 commits intoopenMF:developfrom
ansh-varshney:MX236-Implement-i18n-for-email-SMS

Conversation

@ansh-varshney
Copy link
Copy Markdown

@ansh-varshney ansh-varshney commented Apr 12, 2026

Fixes: MX-236

Replace hardcoded Spanish strings in sendAuthorizationMail() and sendAuthorizationMessage() with Thymeleaf HTML templates and ResourceBundleMessageSource.

Summary by CodeRabbit

  • New Features
    • Registration notifications now use localized messages (English and Spanish) based on user locale.
    • SMS notifications are templated with placeholders for name, request ID, and authorization code.
    • Email notifications now use an HTML template with localized text and injected authorization details for clearer presentation.
  • Chores
    • Added support for localized message bundles and HTML template rendering for registration communications.

…ssages

Replace hardcoded Spanish strings in sendAuthorizationMail() and
sendAuthorizationMessage() with Thymeleaf HTML templates and
ResourceBundleMessageSource.
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 12, 2026

📝 Walkthrough

Walkthrough

Adds Thymeleaf and i18n support for registration notifications: new Thymeleaf Maven dependency, MessageSource and SpringTemplateEngine beans, service updated to use localized SMS/email content, English/Spanish resource bundles, and a Thymeleaf HTML email template.

Changes

Cohort / File(s) Summary
Dependency Management
pom.xml
Added org.thymeleaf:thymeleaf-spring6 Maven dependency.
Service Implementation
src/main/java/org/apache/fineract/selfservice/registration/service/SelfServiceRegistrationWritePlatformServiceImpl.java
Injected SpringTemplateEngine and MessageSource; SMS text and email subject now retrieved from MessageSource (locale-aware); email body rendered via Thymeleaf authorization-email.html with firstName, requestId, authToken.
Spring Configuration
src/main/java/org/apache/fineract/selfservice/registration/starter/SelfRegistrationConfiguration.java
Added registrationMessageSource() bean (ResourceBundleMessageSource, basename i18n/messages, UTF-8) and registrationTemplateEngine() bean (SpringTemplateEngine with ClassLoaderTemplateResolver for mail-templates/*.html); service bean wiring updated to pass new beans.
Message Resources
src/main/resources/i18n/messages.properties, src/main/resources/i18n/messages_es.properties
Added English and Spanish message bundles with keys for email.* and sms.message including placeholders.
Email Template
src/main/resources/mail-templates/authorization-email.html
Added Thymeleaf HTML template using message keys and variables (firstName, requestId, authToken).
Tests
src/test/java/.../SelfServiceRegistrationWritePlatformServiceImplTest.java
Added mocked SpringTemplateEngine and MessageSource; test setup updated to pass new constructor args.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client
    participant RegistrationService as RegistrationService
    participant MessageSource as MessageSource
    participant TemplateEngine as TemplateEngine
    participant SmsService as SmsService
    participant EmailService as EmailService

    Client->>RegistrationService: submit registration request
    RegistrationService->>MessageSource: resolve SMS template (key, args, locale)
    MessageSource-->>RegistrationService: localized SMS text
    RegistrationService->>SmsService: send SMS(phone, text)

    RegistrationService->>MessageSource: resolve email subject (key, locale)
    MessageSource-->>RegistrationService: localized subject
    RegistrationService->>TemplateEngine: render "authorization-email" (firstName, requestId, authToken, locale)
    TemplateEngine-->>RegistrationService: rendered HTML
    RegistrationService->>EmailService: send email(to, subject, html)
    EmailService-->>Client: delivery ack
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • IOhacker
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main objective of the changeset: implementing internationalization for SMS and email messages by replacing hardcoded Spanish strings with i18n infrastructure using Thymeleaf templates and ResourceBundleMessageSource.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch MX236-Implement-i18n-for-email-SMS

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ansh-varshney ansh-varshney changed the title feat(registration): implement i18n for email and SMS authorization me… MX-236: Implement i18N for the messages sent by SMS or Email Apr 12, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/main/java/org/apache/fineract/selfservice/registration/starter/SelfRegistrationConfiguration.java`:
- Around line 52-73: Add Javadoc comments for the two new public bean factory
methods: registrationMessageSource() and registrationTemplateEngine(). For
registrationMessageSource(), add a brief description that it creates and
configures a ResourceBundleMessageSource for i18n (basename "i18n/messages",
UTF-8, no system locale fallback) and document the return type (MessageSource).
For registrationTemplateEngine(), add a brief description that it creates and
configures a SpringTemplateEngine with a ClassLoaderTemplateResolver for mail
HTML templates (prefix "mail-templates/", suffix ".html", HTML mode, UTF-8), and
document the return type (SpringTemplateEngine). Keep descriptions short and
follow existing Javadoc style used in the codebase.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c6d1a5b4-b884-4c53-b59f-02025a33e102

📥 Commits

Reviewing files that changed from the base of the PR and between 8de06be and ecd0f18.

📒 Files selected for processing (6)
  • pom.xml
  • src/main/java/org/apache/fineract/selfservice/registration/service/SelfServiceRegistrationWritePlatformServiceImpl.java
  • src/main/java/org/apache/fineract/selfservice/registration/starter/SelfRegistrationConfiguration.java
  • src/main/resources/i18n/messages.properties
  • src/main/resources/i18n/messages_es.properties
  • src/main/resources/mail-templates/authorization-email.html

Copy link
Copy Markdown
Contributor

@IOhacker IOhacker left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm

@IOhacker
Copy link
Copy Markdown
Contributor

@AnshVarshney there is an issue, check the CI errors

@DeathGun44
Copy link
Copy Markdown
Contributor

@AnshVarshney https://github.com/openMF/selfservice-plugin/blob/develop/TESTING.md take a look, this will help you out to run tests locally so that you can confidently raise the prs!

@ansh-varshney
Copy link
Copy Markdown
Author

Thanks @DeathGun44, will surely look at it!

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/test/java/org/apache/fineract/selfservice/registration/service/SelfServiceRegistrationWritePlatformServiceImplTest.java (1)

67-89: Add behavioral tests for i18n/template usage, not only constructor wiring.

The new mocks are injected, but no test verifies registrationMessageSource.getMessage(...) or registrationTemplateEngine.process(...). This leaves the MX-236 behavior unguarded.

Suggested test extension
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@
+import org.thymeleaf.context.Context;
@@
     `@Test`
+    void createRegistrationRequest_emailMode_usesLocalizedSubjectAndTemplate() {
+        when(fromApiJsonHelper.extractStringNamed(eq(SelfServiceApiConstants.accountNumberParamName), any())).thenReturn("12345");
+        when(fromApiJsonHelper.extractStringNamed(eq(SelfServiceApiConstants.firstNameParamName), any())).thenReturn("John");
+        when(fromApiJsonHelper.extractStringNamed(eq(SelfServiceApiConstants.middleNameParamName), any())).thenReturn(null);
+        when(fromApiJsonHelper.extractStringNamed(eq(SelfServiceApiConstants.lastNameParamName), any())).thenReturn("Doe");
+        when(fromApiJsonHelper.extractStringNamed(eq(SelfServiceApiConstants.usernameParamName), any())).thenReturn("jdoe");
+        when(fromApiJsonHelper.extractStringNamed(eq(SelfServiceApiConstants.passwordParamName), any())).thenReturn("Password123!");
+        when(fromApiJsonHelper.extractStringNamed(eq(SelfServiceApiConstants.authenticationModeParamName), any())).thenReturn("email");
+        when(fromApiJsonHelper.extractStringNamed(eq(SelfServiceApiConstants.emailParamName), any())).thenReturn("john@test.com");
+
+        PasswordValidationPolicy policy = mock(PasswordValidationPolicy.class);
+        when(policy.getRegex()).thenReturn(".*");
+        when(passwordValidationPolicyRepository.findActivePasswordValidationPolicy()).thenReturn(policy);
+        when(appUserReadPlatformService.isUsernameExist("jdoe")).thenReturn(false);
+        when(selfServiceRegistrationReadPlatformService.isClientExist(anyString(), anyString(), any(), anyString(), any(), anyBoolean()))
+                .thenReturn(true);
+        when(clientRepository.getClientByAccountNumber("12345")).thenReturn(mock(Client.class));
+
+        when(registrationMessageSource.getMessage(eq("email.subject"), eq(null), any())).thenReturn("Authorization");
+        when(registrationTemplateEngine.process(eq("authorization-email"), any(Context.class))).thenReturn("<html/>");
+
+        service.createRegistrationRequest("{}");
+
+        verify(registrationMessageSource).getMessage(eq("email.subject"), eq(null), any());
+        verify(registrationTemplateEngine).process(eq("authorization-email"), any(Context.class));
+    }
+
+    `@Test`
     void createRegistrationRequest_persistsRegistration() {

As per coding guidelines, "Verify both happy path and edge cases."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/test/java/org/apache/fineract/selfservice/registration/service/SelfServiceRegistrationWritePlatformServiceImplTest.java`
around lines 67 - 89, Add behavioral tests in
SelfServiceRegistrationWritePlatformServiceImplTest that stub and verify
internationalization and template usage: mock
registrationMessageSource.getMessage(...) to return a known localized string and
assert the service (use the service instance created in setUp) consumes it, and
mock registrationTemplateEngine.process(...) to return rendered HTML and verify
the service calls it with expected template name/variables. Include both a
happy-path test (valid inputs leading to message/template invocation and
expected result) and an edge-case test (missing message/template or null return
values) asserting graceful handling or exceptions. Use Mockito
when(...).thenReturn(...) plus verify(registrationMessageSource).getMessage(...)
and verify(registrationTemplateEngine).process(...) to ensure coverage.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@src/test/java/org/apache/fineract/selfservice/registration/service/SelfServiceRegistrationWritePlatformServiceImplTest.java`:
- Around line 67-89: Add behavioral tests in
SelfServiceRegistrationWritePlatformServiceImplTest that stub and verify
internationalization and template usage: mock
registrationMessageSource.getMessage(...) to return a known localized string and
assert the service (use the service instance created in setUp) consumes it, and
mock registrationTemplateEngine.process(...) to return rendered HTML and verify
the service calls it with expected template name/variables. Include both a
happy-path test (valid inputs leading to message/template invocation and
expected result) and an edge-case test (missing message/template or null return
values) asserting graceful handling or exceptions. Use Mockito
when(...).thenReturn(...) plus verify(registrationMessageSource).getMessage(...)
and verify(registrationTemplateEngine).process(...) to ensure coverage.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ea5d5a0f-2bb2-4b75-8bc0-c52b95c8afe0

📥 Commits

Reviewing files that changed from the base of the PR and between 4e58eb7 and d7c274c.

📒 Files selected for processing (1)
  • src/test/java/org/apache/fineract/selfservice/registration/service/SelfServiceRegistrationWritePlatformServiceImplTest.java

@ansh-varshney
Copy link
Copy Markdown
Author

It appears that the local compilation failures are pre-existing on develop and caused by missing fineract-*:1.15.0-SNAPSHOT JARs in the local Maven cache.

I have checked all 3 test files covering the changed classes in this pr and it appeared that only CI failure introduced by this pr was constructor mismatch in SelfServiceRegistrationWritePlatformServiceImplTest.

I have fixed this now.

@IOhacker
Copy link
Copy Markdown
Contributor

@ansh-varshney help me to resolve the conflicts too

@ansh-varshney
Copy link
Copy Markdown
Author

@ansh-varshney help me to resolve the conflicts too

Yes, I am on it. I'll provide a brief explanation about what should de done acc to me for conflict resoltuion.

@ansh-varshney
Copy link
Copy Markdown
Author

@IOhacker,
for first conflict: src/main/java/org/apache/fineract/selfservice/registration/service/SelfServiceRegistrationWritePlatformServiceImpl.java
imports and fields are only being added, should not be any issue.
We should keep both the changes.

@ansh-varshney
Copy link
Copy Markdown
Author

@IOhacker,
src/main/java/org/apache/fineract/selfservice/registration/starter/SelfRegistrationConfiguration.java
similarly for the second one also, new arguments are being added only to the constructor.
still should keep both, but we need to make sure that order here matches order of private final fields in the impl class after resolving.

@ansh-varshney
Copy link
Copy Markdown
Author

@IOhacker, same for the third file also - same pattern only. lets keep both.

@IOhacker
Copy link
Copy Markdown
Contributor

Hi Ansh, could you please rebase?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants