FIX: prevents i18n helper to return a SafeString (#9191)

For convenience the i18n helper has been made returning a SafeString, but when used with other helpers, a String is expected and will cause unexpected behaviors.

This is the root cause of the initial bug fixed in d2bb127e2c

This commit is kept as it's a better security in case of unexpected behavior.
This commit is contained in:
Joffrey JAFFEUX 2020-03-12 16:50:20 +01:00 committed by GitHub
parent 59578dfc5b
commit 6102c287f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 58 additions and 57 deletions

View File

@ -15,7 +15,7 @@
{{#if backupStats.last_backup_taken_at}} {{#if backupStats.last_backup_taken_at}}
<br> <br>
{{i18n "admin.dashboard.lastest_backup" date=(format-date backupStats.last_backup_taken_at leaveAgo="true")}} {{html-safe (i18n "admin.dashboard.lastest_backup" date=(format-date backupStats.last_backup_taken_at leaveAgo="true"))}}
{{/if}} {{/if}}
</p> </p>
</div> </div>

View File

@ -1,7 +1,7 @@
<div class='penalty-post-controls'> <div class='penalty-post-controls'>
<label> <label>
<div class='penalty-post-label'> <div class='penalty-post-label'>
{{i18n 'admin.user.penalty_post_actions'}} {{html-safe (i18n 'admin.user.penalty_post_actions')}}
</div> </div>
</label> </label>
{{combo-box {{combo-box

View File

@ -1,7 +1,7 @@
<div class='reason-controls'> <div class='reason-controls'>
<label> <label>
<div class='silence-reason-label'> <div class='silence-reason-label'>
{{i18n 'admin.user.silence_reason_label'}} {{html-safe (i18n 'admin.user.silence_reason_label')}}
</div> </div>
</label> </label>
{{text-field {{text-field

View File

@ -2,9 +2,9 @@
<label> <label>
<div class='suspend-reason-label'> <div class='suspend-reason-label'>
{{#if siteSettings.hide_suspension_reasons}} {{#if siteSettings.hide_suspension_reasons}}
{{i18n 'admin.user.suspend_reason_hidden_label'}} {{html-safe (i18n 'admin.user.suspend_reason_hidden_label')}}
{{else}} {{else}}
{{i18n 'admin.user.suspend_reason_label'}} {{html-safe (i18n 'admin.user.suspend_reason_label')}}
{{/if}} {{/if}}
</div> </div>
</label> </label>

View File

@ -142,7 +142,7 @@
filters=trendingSearchFilters filters=trendingSearchFilters
isEnabled=logSearchQueriesEnabled isEnabled=logSearchQueriesEnabled
disabledLabel=trendingSearchDisabledLabel}} disabledLabel=trendingSearchDisabledLabel}}
{{i18n "admin.dashboard.reports.trending_search.more" basePath=basePath}} {{html-safe (i18n "admin.dashboard.reports.trending_search.more" basePath=basePath)}}
</div> </div>
</div> </div>

View File

@ -23,7 +23,7 @@
{{#if showSecondary}} {{#if showSecondary}}
<div class='embedding-secondary'> <div class='embedding-secondary'>
<p>{{i18n "admin.embedding.sample"}}</p> <p>{{html-safe (i18n "admin.embedding.sample")}}</p>
{{highlighted-code code=embeddingCode lang="html"}} {{highlighted-code code=embeddingCode lang="html"}}
</div> </div>

View File

@ -17,9 +17,9 @@
{{else}} {{else}}
<p class="grant-count"> <p class="grant-count">
{{#if count}} {{#if count}}
{{i18n "admin.badges.preview.grant_count" count=count}} {{html-safe (i18n "admin.badges.preview.grant_count" count=count)}}
{{else}} {{else}}
{{i18n "admin.badges.preview.no_grant_count"}} {{html-safe (i18n "admin.badges.preview.no_grant_count")}}
{{/if}} {{/if}}
</p> </p>

View File

@ -132,7 +132,7 @@
<div class="field">{{i18n "user.avatar.title"}}</div> <div class="field">{{i18n "user.avatar.title"}}</div>
<div class="value">{{avatar model imageSize="large"}}</div> <div class="value">{{avatar model imageSize="large"}}</div>
<div class="controls"> <div class="controls">
{{i18n "admin.user.visit_profile" url=preferencesPath}} {{html-safe (i18n "admin.user.visit_profile" url=preferencesPath)}}
</div> </div>
</div> </div>

View File

@ -1,7 +1,6 @@
import { registerUnbound } from "discourse-common/lib/helpers"; import { registerUnbound } from "discourse-common/lib/helpers";
import { htmlSafe } from "@ember/template";
registerUnbound("i18n", (key, params) => htmlSafe(I18n.t(key, params))); registerUnbound("i18n", (key, params) => I18n.t(key, params));
registerUnbound("i18n-yes-no", (value, params) => registerUnbound("i18n-yes-no", (value, params) =>
I18n.t(value ? "yes_value" : "no_value", params) I18n.t(value ? "yes_value" : "no_value", params)
); );

View File

@ -1,7 +1,7 @@
import { registerUnbound } from "discourse-common/lib/helpers"; import { registerUnbound } from "discourse-common/lib/helpers";
import { emojiUnescape } from "discourse/lib/text"; import { emojiUnescape } from "discourse/lib/text";
import { htmlSafe } from "@ember/template";
registerUnbound( registerUnbound("replace-emoji", text => {
"replace-emoji", return htmlSafe(emojiUnescape(text));
text => new Handlebars.SafeString(emojiUnescape(text)) });
);

View File

@ -1,6 +1,6 @@
<div class='ac-message'> <div class='ac-message'>
{{#if email}} {{#if email}}
{{i18n 'login.sent_activation_email_again' currentEmail=email}} {{html-safe (i18n 'login.sent_activation_email_again' currentEmail=email)}}
{{else}} {{else}}
{{i18n 'login.sent_activation_email_again_generic'}} {{i18n 'login.sent_activation_email_again_generic'}}
{{/if}} {{/if}}

View File

@ -5,7 +5,7 @@
<div id="banner-content"> <div id="banner-content">
{{html-safe content}} {{html-safe content}}
{{#if currentUser.staff}} {{#if currentUser.staff}}
<p><a href={{banner.url}}>{{i18n "banner.edit"}}</a></p> <p><a href={{banner.url}}>{{html-safe (i18n "banner.edit")}}</a></p>
{{/if}} {{/if}}
</div> </div>
</div> </div>

View File

@ -1,7 +1,7 @@
{{#if category.isUncategorizedCategory}} {{#if category.isUncategorizedCategory}}
<p class="warning"> <p class="warning">
{{d-icon "exclamation-triangle"}} {{d-icon "exclamation-triangle"}}
{{i18n 'category.uncategorized_general_warning' settingLink=uncategorizedSiteSettingLink customizeLink=customizeTextContentLink}} {{html-safe (i18n 'category.uncategorized_general_warning' settingLink=uncategorizedSiteSettingLink customizeLink=customizeTextContentLink)}}
</p> </p>
{{/if}} {{/if}}

View File

@ -11,7 +11,7 @@
{{#each category.permissions as |p|}} {{#each category.permissions as |p|}}
<li> <li>
<span class="name"><span class="badge-group">{{p.group_name}}</span></span> <span class="name"><span class="badge-group">{{p.group_name}}</span></span>
{{i18n "category.can"}} {{html-safe (i18n "category.can")}}
<span class="permission">{{p.permission.description}}</span> <span class="permission">{{p.permission.description}}</span>
{{#if editingPermissions}} {{#if editingPermissions}}
<a class="remove-permission" href {{action "removePermission" p}}>{{d-icon "times-circle"}}</a> <a class="remove-permission" href {{action "removePermission" p}}>{{d-icon "times-circle"}}</a>

View File

@ -14,7 +14,7 @@
{{d-button action=(action "copy") class="pull-right no-text" icon="copy"}} {{d-button action=(action "copy") class="pull-right no-text" icon="copy"}}
{{/if}} {{/if}}
<h4>{{i18n "ip_lookup.title"}}</h4> <h4>{{i18n "ip_lookup.title"}}</h4>
<p class='powered-by'>{{i18n "ip_lookup.powered_by"}}</p> <p class='powered-by'>{{html-safe (i18n "ip_lookup.powered_by")}}</p>
<dl> <dl>
{{#if location}} {{#if location}}
{{#if location.hostname}} {{#if location.hostname}}

View File

@ -10,5 +10,5 @@
</div> </div>
{{#if targetUser}} {{#if targetUser}}
<h3 class="see-all-pms-message">{{i18n "related_messages.see_all" path=searchLink username=targetUser.username}}</h3> <h3 class="see-all-pms-message">{{html-safe (i18n "related_messages.see_all" path=searchLink username=targetUser.username)}}</h3>
{{/if}} {{/if}}

View File

@ -2,7 +2,7 @@
{{#if publishing}} {{#if publishing}}
{{i18n "shared_drafts.publishing"}} {{i18n "shared_drafts.publishing"}}
{{else}} {{else}}
{{i18n "shared_drafts.notice" category=topic.category.name}} {{html-safe (i18n "shared_drafts.notice" category=topic.category.name)}}
<div class='publish-field'> <div class='publish-field'>
<label>{{i18n "shared_drafts.destination_category"}}</label> <label>{{i18n "shared_drafts.destination_category"}}</label>

View File

@ -32,7 +32,7 @@
{{#if tagInfo.synonyms}} {{#if tagInfo.synonyms}}
<div class="synonyms-list"> <div class="synonyms-list">
<h3>{{i18n "tagging.synonyms"}}</h3> <h3>{{i18n "tagging.synonyms"}}</h3>
<div>{{i18n "tagging.synonyms_description" base_tag_name=tagInfo.name}}</div> <div>{{html-safe (i18n "tagging.synonyms_description" base_tag_name=tagInfo.name)}}</div>
<div class="tag-list"> <div class="tag-list">
{{#each tagInfo.synonyms as |tag|}} {{#each tagInfo.synonyms as |tag|}}
<div class='tag-box'> <div class='tag-box'>

View File

@ -9,5 +9,5 @@
</span> </span>
<span class='label'> <span class='label'>
{{#if icon}}{{d-icon icon}}{{/if}} {{#if icon}}{{d-icon icon}}{{/if}}
{{i18n label count=value}} {{html-safe (i18n label count=value)}}
</span> </span>

View File

@ -1,5 +1,5 @@
{{#d-modal-body}} {{#d-modal-body}}
{{i18n 'login.sent_activation_email_again' currentEmail=currentEmail}} {{html-safe (i18n 'login.sent_activation_email_again' currentEmail=currentEmail)}}
{{/d-modal-body}} {{/d-modal-body}}
{{modal-footer-close closeModal=(route-action "closeModal")}} {{modal-footer-close closeModal=(route-action "closeModal")}}

View File

@ -1,7 +1,7 @@
{{#d-modal-body title="user.auth_tokens.was_this_you"}} {{#d-modal-body title="user.auth_tokens.was_this_you"}}
<div> <div>
<p>{{i18n 'user.auth_tokens.was_this_you_description'}}</p> <p>{{i18n 'user.auth_tokens.was_this_you_description'}}</p>
<p>{{i18n 'user.second_factor.extended_description'}}</p> <p>{{html-safe (i18n 'user.second_factor.extended_description')}}</p>
</div> </div>
<div> <div>

View File

@ -10,11 +10,11 @@
{{else}} {{else}}
<div class="avatar-choice"> <div class="avatar-choice">
{{radio-button id="system-avatar" name="avatar" value="system" selection=selected}} {{radio-button id="system-avatar" name="avatar" value="system" selection=selected}}
<label class="radio" for="system-avatar">{{bound-avatar-template user.system_avatar_template "large"}} {{i18n 'user.change_avatar.letter_based'}}</label> <label class="radio" for="system-avatar">{{bound-avatar-template user.system_avatar_template "large"}} {{html-safe (i18n 'user.change_avatar.letter_based')}}</label>
</div> </div>
<div class="avatar-choice"> <div class="avatar-choice">
{{radio-button id="gravatar" name="avatar" value="gravatar" selection=selected}} {{radio-button id="gravatar" name="avatar" value="gravatar" selection=selected}}
<label class="radio" for="gravatar">{{bound-avatar-template user.gravatar_avatar_template "large"}} <span>{{i18n 'user.change_avatar.gravatar' gravatarName=gravatarName gravatarBaseUrl=gravatarBaseUrl gravatarLoginUrl=gravatarLoginUrl }} {{user.email}}</span></label> <label class="radio" for="gravatar">{{bound-avatar-template user.gravatar_avatar_template "large"}} <span>{{html-safe (i18n 'user.change_avatar.gravatar' gravatarName=gravatarName gravatarBaseUrl=gravatarBaseUrl gravatarLoginUrl=gravatarLoginUrl)}} {{user.email}}</span></label>
{{d-button action=(action "refreshGravatar") {{d-button action=(action "refreshGravatar")
translatedTitle=(i18n "user.change_avatar.refresh_gravatar_title" gravatarName=gravatarName) translatedTitle=(i18n "user.change_avatar.refresh_gravatar_title" gravatarName=gravatarName)

View File

@ -50,7 +50,7 @@
{{/if}} {{/if}}
{{else}} {{else}}
<div class="alert alert-info">{{i18n "bookmarks.no_timezone" basePath=basePath }}</div> <div class="alert alert-info">{{html-safe (i18n "bookmarks.no_timezone" basePath=basePath)}}</div>
{{/if}} {{/if}}
</div> </div>
{{/if}} {{/if}}

View File

@ -1,8 +1,10 @@
{{#d-modal-body class='change-ownership'}} {{#d-modal-body class='change-ownership'}}
<span> <span>
{{i18n (if selectedPostsUsername 'topic.change_owner.instructions' 'topic.change_owner.instructions_without_old_user') {{html-safe (i18n (if selectedPostsUsername 'topic.change_owner.instructions' 'topic.change_owner.instructions_without_old_user')
count=selectedPostsCount count=selectedPostsCount
old_user=selectedPostsUsername}} old_user=selectedPostsUsername
)
}}
</span> </span>
<form> <form>

View File

@ -1,5 +1,5 @@
{{#d-modal-body}} {{#d-modal-body}}
<p>{{i18n "post.controls.delete_topic_disallowed_modal"}}</p> <p>{{html-safe (i18n "post.controls.delete_topic_disallowed_modal")}}</p>
{{/d-modal-body}} {{/d-modal-body}}
<div class="modal-footer"> <div class="modal-footer">
{{d-button action=(route-action "closeModal") class="btn-primary" label="close"}} {{d-button action=(route-action "closeModal") class="btn-primary" label="close"}}

View File

@ -6,9 +6,9 @@
<p> <p>
{{#conditional-loading-spinner size="small" condition=loading}} {{#conditional-loading-spinner size="small" condition=loading}}
{{#if pinnedGloballyCount}} {{#if pinnedGloballyCount}}
{{i18n "topic.feature_topic.already_pinned_globally" count=pinnedGloballyCount}} {{html-safe (i18n "topic.feature_topic.already_pinned_globally" count=pinnedGloballyCount)}}
{{else}} {{else}}
{{i18n "topic.feature_topic.not_pinned_globally"}} {{html-safe (i18n "topic.feature_topic.not_pinned_globally")}}
{{/if}} {{/if}}
{{/conditional-loading-spinner}} {{/conditional-loading-spinner}}
</p> </p>
@ -74,9 +74,9 @@
<p> <p>
{{#conditional-loading-spinner size="small" condition=loading}} {{#conditional-loading-spinner size="small" condition=loading}}
{{#if pinnedGloballyCount}} {{#if pinnedGloballyCount}}
{{i18n "topic.feature_topic.already_pinned_globally" count=pinnedGloballyCount}} {{html-safe (i18n "topic.feature_topic.already_pinned_globally" count=pinnedGloballyCount)}}
{{else}} {{else}}
{{i18n "topic.feature_topic.not_pinned_globally"}} {{html-safe (i18n "topic.feature_topic.not_pinned_globally")}}
{{/if}} {{/if}}
{{/conditional-loading-spinner}} {{/conditional-loading-spinner}}
</p> </p>
@ -123,9 +123,9 @@
<p> <p>
{{#conditional-loading-spinner size="small" condition=loading}} {{#conditional-loading-spinner size="small" condition=loading}}
{{#if bannerCount}} {{#if bannerCount}}
{{i18n "topic.feature_topic.banner_exists"}} {{html-safe (i18n "topic.feature_topic.banner_exists")}}
{{else}} {{else}}
{{i18n "topic.feature_topic.no_banner_exists"}} {{html-safe (i18n "topic.feature_topic.no_banner_exists")}}
{{/if}} {{/if}}
{{/conditional-loading-spinner}} {{/conditional-loading-spinner}}
</p> </p>

View File

@ -17,7 +17,7 @@
{{#if canSplitTopic}} {{#if canSplitTopic}}
{{#if newMessage}} {{#if newMessage}}
<p>{{i18n 'topic.move_to_new_message.instructions' count=selectedPostsCount}}</p> <p>{{html-safe (i18n 'topic.move_to_new_message.instructions' count=selectedPostsCount)}}</p>
<form> <form>
<label>{{i18n 'topic.move_to_new_message.message_title'}}</label> <label>{{i18n 'topic.move_to_new_message.message_title'}}</label>
{{text-field value=topicName placeholderKey="composer.title_placeholder" elementId='split-topic-name'}} {{text-field value=topicName placeholderKey="composer.title_placeholder" elementId='split-topic-name'}}
@ -31,7 +31,7 @@
{{/if}} {{/if}}
{{#if existingMessage}} {{#if existingMessage}}
<p>{{i18n 'topic.move_to_existing_message.instructions' count=selectedPostsCount}}</p> <p>{{html-safe (i18n 'topic.move_to_existing_message.instructions' count=selectedPostsCount)}}</p>
<form> <form>
{{choose-message currentTopicId=model.id selectedTopicId=selectedTopicId}} {{choose-message currentTopicId=model.id selectedTopicId=selectedTopicId}}
@ -64,7 +64,7 @@
</div> </div>
{{#if existingTopic}} {{#if existingTopic}}
<p>{{i18n 'topic.merge_topic.instructions' count=selectedPostsCount}}</p> <p>{{html-safe (i18n 'topic.merge_topic.instructions' count=selectedPostsCount)}}</p>
<form> <form>
{{choose-topic currentTopicId=model.id selectedTopicId=selectedTopicId}} {{choose-topic currentTopicId=model.id selectedTopicId=selectedTopicId}}
</form> </form>
@ -72,7 +72,7 @@
{{#if canSplitTopic}} {{#if canSplitTopic}}
{{#if newTopic}} {{#if newTopic}}
<p>{{i18n 'topic.split_topic.instructions' count=selectedPostsCount}}</p> <p>{{html-safe (i18n 'topic.split_topic.instructions' count=selectedPostsCount)}}</p>
<form> <form>
<label>{{i18n 'topic.split_topic.topic_name'}}</label> <label>{{i18n 'topic.split_topic.topic_name'}}</label>
{{text-field value=topicName placeholderKey="composer.title_placeholder" elementId='split-topic-name'}} {{text-field value=topicName placeholderKey="composer.title_placeholder" elementId='split-topic-name'}}
@ -93,7 +93,7 @@
{{#if canSplitTopic}} {{#if canSplitTopic}}
{{#if newMessage}} {{#if newMessage}}
<p>{{i18n 'topic.move_to_new_message.instructions' count=selectedPostsCount}}</p> <p>{{html-safe (i18n 'topic.move_to_new_message.instructions' count=selectedPostsCount)}}</p>
<form> <form>
<label>{{i18n 'topic.move_to_new_message.message_title'}}</label> <label>{{i18n 'topic.move_to_new_message.message_title'}}</label>
{{text-field value=topicName placeholderKey="composer.title_placeholder" elementId='split-topic-name'}} {{text-field value=topicName placeholderKey="composer.title_placeholder" elementId='split-topic-name'}}

View File

@ -1,5 +1,5 @@
{{#d-modal-body}} {{#d-modal-body}}
{{i18n 'login.not_activated' sentTo=sentTo}} {{html-safe (i18n 'login.not_activated' sentTo=sentTo)}}
{{/d-modal-body}} {{/d-modal-body}}
<div class="modal-footer"> <div class="modal-footer">

View File

@ -1,7 +1,7 @@
{{#d-modal-body}} {{#d-modal-body}}
<p>{{i18n "review.approval.description"}}</p> <p>{{i18n "review.approval.description"}}</p>
<p>{{i18n "review.approval.pending_posts" count=model.pending_count}}</p> <p>{{html-safe (i18n "review.approval.pending_posts" count=model.pending_count)}}</p>
{{/d-modal-body}} {{/d-modal-body}}
<div class="modal-footer"> <div class="modal-footer">
{{d-button action=(route-action "closeModal") class="btn-primary" label="review.approval.ok"}} {{d-button action=(route-action "closeModal") class="btn-primary" label="review.approval.ok"}}

View File

@ -10,7 +10,7 @@
<div class="control-group"> <div class="control-group">
<div class="controls"> <div class="controls">
{{i18n 'user.second_factor.enable_security_key_description'}} {{html-safe (i18n 'user.second_factor.enable_security_key_description')}}
</div> </div>
</div> </div>

View File

@ -10,7 +10,7 @@
<div class="control-group"> <div class="control-group">
<div class="controls"> <div class="controls">
{{i18n 'user.second_factor.enable_description'}} {{html-safe (i18n 'user.second_factor.enable_description')}}
</div> </div>
</div> </div>

View File

@ -14,7 +14,7 @@
{{/if}} {{/if}}
{{#if backupEnabled}} {{#if backupEnabled}}
{{i18n "user.second_factor_backup.remaining_codes" count=remainingCodes}} {{html-safe (i18n "user.second_factor_backup.remaining_codes" count=remainingCodes)}}
{{/if}} {{/if}}
<div class="actions"> <div class="actions">

View File

@ -1,4 +1,4 @@
{{#d-modal-body}} {{#d-modal-body}}
<p>{{i18n 'topics.bulk.selected' count=model.topics.length}}</p> <p>{{html-safe (i18n 'topics.bulk.selected' count=model.topics.length)}}</p>
{{outlet "bulkOutlet"}} {{outlet "bulkOutlet"}}
{{/d-modal-body}} {{/d-modal-body}}

View File

@ -86,7 +86,7 @@
<h2>{{i18n "user.second_factor_backup.title"}}</h2> <h2>{{i18n "user.second_factor_backup.title"}}</h2>
{{#if model.second_factor_enabled}} {{#if model.second_factor_enabled}}
{{#if model.second_factor_backup_enabled}} {{#if model.second_factor_backup_enabled}}
{{i18n 'user.second_factor_backup.manage' count=model.second_factor_remaining_backup_codes}} {{html-safe (i18n 'user.second_factor_backup.manage' count=model.second_factor_remaining_backup_codes)}}
{{else}} {{else}}
{{i18n 'user.second_factor_backup.enable_long'}} {{i18n 'user.second_factor_backup.enable_long'}}
{{/if}} {{/if}}

View File

@ -9,7 +9,7 @@
</div> </div>
{{#if siteSettings.enable_mentions}} {{#if siteSettings.enable_mentions}}
<div class='instructions'> <div class='instructions'>
{{i18n 'user.username.short_instructions' username=model.username}} {{html-safe (i18n 'user.username.short_instructions' username=model.username)}}
</div> </div>
{{/if}} {{/if}}
</div> </div>

View File

@ -73,7 +73,7 @@
<div class='control-group pref-mailing-list-mode'> <div class='control-group pref-mailing-list-mode'>
<label class="control-label">{{i18n 'user.mailing_list_mode.label'}}</label> <label class="control-label">{{i18n 'user.mailing_list_mode.label'}}</label>
{{preference-checkbox labelKey="user.mailing_list_mode.enabled" checked=model.user_option.mailing_list_mode}} {{preference-checkbox labelKey="user.mailing_list_mode.enabled" checked=model.user_option.mailing_list_mode}}
<div class='instructions'>{{i18n 'user.mailing_list_mode.instructions'}}</div> <div class='instructions'>{{html-safe (i18n 'user.mailing_list_mode.instructions')}}</div>
{{#if model.user_option.mailing_list_mode}} {{#if model.user_option.mailing_list_mode}}
<div class='controls controls-dropdown'> <div class='controls controls-dropdown'>
{{combo-box {{combo-box

View File

@ -277,7 +277,7 @@
{{#if model.queued_posts_count}} {{#if model.queued_posts_count}}
<div class="has-pending-posts"> <div class="has-pending-posts">
<div> <div>
{{i18n "review.topic_has_pending" count=model.queued_posts_count}} {{html-safe (i18n "review.topic_has_pending" count=model.queued_posts_count)}}
</div> </div>
{{#link-to 'review' (query-params topic_id=model.id type="ReviewableQueuedPost" status="pending")}} {{#link-to 'review' (query-params topic_id=model.id type="ReviewableQueuedPost" status="pending")}}

View File

@ -109,7 +109,7 @@
{{else}} {{else}}
<div class="user-invite-none"> <div class="user-invite-none">
{{#if canBulkInvite}} {{#if canBulkInvite}}
{{i18n 'user.invited.bulk_invite.none'}} {{html-safe (i18n 'user.invited.bulk_invite.none')}}
{{else}} {{else}}
{{i18n 'user.invited.none'}} {{i18n 'user.invited.none'}}
{{/if}} {{/if}}

View File

@ -85,7 +85,7 @@
<label class="control-label"> <label class="control-label">
{{i18n "discourse_local_dates.create.form.recurring_title"}} {{i18n "discourse_local_dates.create.form.recurring_title"}}
</label> </label>
<p>{{i18n "discourse_local_dates.create.form.recurring_description"}}</p> <p>{{html-safe (i18n "discourse_local_dates.create.form.recurring_description")}}</p>
<div class="controls"> <div class="controls">
{{combo-box {{combo-box
content=recurringOptions content=recurringOptions