- Published on
Translating Meteor apps: UI, user generated content and emails
- Authors
- Name
- Peter Peerdeman
- @peterpeerdeman
So one of our meteor apps is fully translated, including all ui, notifications and emails being sent to the clients. We've made heavy use of tap-i18n to achieve this, along with meteorhacks:ssr to render dynamic blaze emailtemplates on the backend.
ui
tap-i18n
makes it incredibly easy to translate ui using labels. We add translation files in an i18n
folder in the root of the project, as simple json files:
{
"activity-button-archive": "Mark as completed",
"activity-button-edit": "Edit",
"activity-button-next_page": "Next step",
"activity-form-description-label": "Describe the activity"
}
Inside the blaze component, we then render the label using the tap-i18n helper with an _
like so:
{{# if activity.archived }}
<a class="pu-button" data-activity-unarchive>{{_ 'activity-button-unarchive'}}</a>
{{ else }}
<a class="pu-button" data-activity-archive>{{_ 'activity-button-archive'}}</a>
{{/ if }}
All thats left now, is configuring which language should be loaded in the client. As documented in the tapi18n documentation, this can be done in the following way while bootstrapping the application:
getUserLanguage = function () {
// Put here the logic for determining the user language
return 'nl';
};
if (Meteor.isClient) {
Meteor.startup(function () {
Session.set('showLoadingIndicator', true);
TAPi18n.setLanguage(getUserLanguage())
.done(function () {
Session.set('showLoadingIndicator', false);
})
.fail(function (error_message) {
// Handle the situation
console.log(error_message);
});
});
}
emails
To render translated emails and send them to users, we create separate emailtemplates with a predictable filename, e.g. reset_password.en.html
and reset_password.nl.html
with contents being translated versions of the same email, including placeholders:
<!-- private/emails/reset_password.en.html -->
<p>
Hi {{ user.profile.name }}! You told us you wanted to reset your password. That's okay! Just
click the link below:
<a href="{{ url }}">{{ url }}</a>
</p>
Before we can use the meteorhacks:ssr
module to render a template, we have to precompile the html template and assign it to a key that we can use later. We indexed all of the emails and locales in some variables and loop through these to pre-compile all of the templates:
// bootstrap.js
var locales = ['en', 'nl'];
var templates = [
'reset_password',
//... rest of the emailtemplates ...
];
SSR.compileTemplate(
'email-' + type + '-' + locale,
Assets.getText('private/emails/' + type + '.' + locale + '.html')
);
When configuring the emails of the accounts package, we use the meteorhacks:ssr
module to render the correct template with a data object containing the variable fields:
/\*\*
- Password Reset Email
\*/
Accounts.emailTemplates.resetPassword.html = function(user, url) {
return SSR.render('email-reset_password-' + User(user).getLocale(), {
user: user,
url: url.replace('/#', ''),
baseUrl: Meteor.absoluteUrl()
});
};