diff --git a/app/models/translation_override.rb b/app/models/translation_override.rb
index 32e45186d11..41334c3c24a 100644
--- a/app/models/translation_override.rb
+++ b/app/models/translation_override.rb
@@ -138,7 +138,8 @@ class TranslationOverride < ActiveRecord::Base
:base,
I18n.t(
"activerecord.errors.models.translation_overrides.attributes.value.invalid_interpolation_keys",
- keys: invalid_keys.join(", "),
+ keys: invalid_keys.join(I18n.t("word_connector.comma")),
+ count: invalid_keys.size,
),
)
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 2e3fdd52cd2..d855d9c87aa 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -161,6 +161,9 @@ en:
email: "Send via email"
url: "Copy and share URL"
+ word_connector:
+ comma: ", "
+
action_codes:
public_topic: "Made this topic public %{when}"
open_topic: "Converted this to a topic %{when}"
diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index 3669228720b..120551cb510 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -641,7 +641,9 @@ en:
translation_overrides:
attributes:
value:
- invalid_interpolation_keys: 'The following interpolation key(s) are invalid: "%{keys}"'
+ invalid_interpolation_keys:
+ one: 'The following interpolation key is invalid: %{keys}'
+ other: 'The following interpolation keys are invalid: %{keys}'
watched_word:
attributes:
word:
diff --git a/plugins/chat/app/models/chat_channel.rb b/plugins/chat/app/models/chat_channel.rb
index beb38e15a8f..35f427a2049 100644
--- a/plugins/chat/app/models/chat_channel.rb
+++ b/plugins/chat/app/models/chat_channel.rb
@@ -75,10 +75,6 @@ class ChatChannel < ActiveRecord::Base
Chat::ChatChannelMembershipManager.new(self).unfollow(user)
end
- def status_name
- I18n.t("chat.channel.statuses.#{self.status}")
- end
-
def url
"#{Discourse.base_url}/chat/c/#{self.slug || "-"}/#{self.id}"
end
diff --git a/plugins/chat/app/models/chat_message.rb b/plugins/chat/app/models/chat_message.rb
index 677c14aa222..6b485036a31 100644
--- a/plugins/chat/app/models/chat_message.rb
+++ b/plugins/chat/app/models/chat_message.rb
@@ -52,7 +52,7 @@ class ChatMessage < ActiveRecord::Base
:base,
I18n.t(
"chat.errors.minimum_length_not_met",
- minimum: SiteSetting.chat_minimum_message_length,
+ count: SiteSetting.chat_minimum_message_length,
),
)
end
@@ -60,7 +60,7 @@ class ChatMessage < ActiveRecord::Base
if message_too_long?
self.errors.add(
:base,
- I18n.t("chat.errors.message_too_long", maximum: SiteSetting.chat_maximum_message_length),
+ I18n.t("chat.errors.message_too_long", count: SiteSetting.chat_maximum_message_length),
)
end
end
diff --git a/plugins/chat/app/models/direct_message.rb b/plugins/chat/app/models/direct_message.rb
index 40ad99c4723..58427608f15 100644
--- a/plugins/chat/app/models/direct_message.rb
+++ b/plugins/chat/app/models/direct_message.rb
@@ -25,7 +25,7 @@ class DirectMessage < ActiveRecord::Base
# direct message to self
if users.empty?
- return I18n.t("chat.channel.dm_title.single_user", user: "@#{acting_user.username}")
+ return I18n.t("chat.channel.dm_title.single_user", username: "@#{acting_user.username}")
end
# all users deleted
@@ -36,13 +36,16 @@ class DirectMessage < ActiveRecord::Base
return(
I18n.t(
"chat.channel.dm_title.multi_user_truncated",
- users: usernames_formatted[0..4].join(", "),
- leftover: usernames_formatted.length - 5,
+ comma_separated_usernames: usernames_formatted[0..4].join(I18n.t("word_connector.comma")),
+ count: usernames_formatted.length - 5,
)
)
end
- I18n.t("chat.channel.dm_title.multi_user", users: usernames_formatted.join(", "))
+ I18n.t(
+ "chat.channel.dm_title.multi_user",
+ comma_separated_usernames: usernames_formatted.join(I18n.t("word_connector.comma")),
+ )
end
end
diff --git a/plugins/chat/app/serializers/chat_message_serializer.rb b/plugins/chat/app/serializers/chat_message_serializer.rb
index 66e96535402..9f6dc19a23e 100644
--- a/plugins/chat/app/serializers/chat_message_serializer.rb
+++ b/plugins/chat/app/serializers/chat_message_serializer.rb
@@ -40,7 +40,7 @@ class ChatMessageSerializer < ApplicationSerializer
.reactions
.group_by(&:emoji)
.each do |emoji, reactions|
- users = reactions[0..6].map(&:user).filter { |user| user.id != scope&.user&.id }[0..5]
+ users = reactions[0..5].map(&:user).filter { |user| user.id != scope&.user&.id }[0..4]
next unless Emoji.exists?(emoji)
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-status.js b/plugins/chat/assets/javascripts/discourse/components/chat-channel-status.js
index f6048b21b9d..cfbd949cdac 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-channel-status.js
+++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel-status.js
@@ -4,7 +4,6 @@ import Component from "@ember/component";
import {
CHANNEL_STATUSES,
channelStatusIcon,
- channelStatusName,
} from "discourse/plugins/chat/discourse/models/chat-channel";
export default Component.extend({
@@ -38,20 +37,28 @@ export default Component.extend({
},
_shortStatusMessage(channelStatus) {
- return channelStatusName(channelStatus);
+ switch (channelStatus) {
+ case CHANNEL_STATUSES.archived:
+ return I18n.t("chat.channel_status.archived");
+ case CHANNEL_STATUSES.closed:
+ return I18n.t("chat.channel_status.closed");
+ case CHANNEL_STATUSES.open:
+ return I18n.t("chat.channel_status.open");
+ case CHANNEL_STATUSES.readOnly:
+ return I18n.t("chat.channel_status.read_only");
+ }
},
_longStatusMessage(channelStatus) {
switch (channelStatus) {
- case CHANNEL_STATUSES.closed:
- return I18n.t("chat.channel_status.closed_header");
- break;
- case CHANNEL_STATUSES.readOnly:
- return I18n.t("chat.channel_status.read_only_header");
- break;
case CHANNEL_STATUSES.archived:
return I18n.t("chat.channel_status.archived_header");
- break;
+ case CHANNEL_STATUSES.closed:
+ return I18n.t("chat.channel_status.closed_header");
+ case CHANNEL_STATUSES.open:
+ return I18n.t("chat.channel_status.open_header");
+ case CHANNEL_STATUSES.readOnly:
+ return I18n.t("chat.channel_status.read_only_header");
}
},
});
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-composer.js b/plugins/chat/assets/javascripts/discourse/components/chat-composer.js
index 567df1590cc..315083f6fe2 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-composer.js
+++ b/plugins/chat/assets/javascripts/discourse/components/chat-composer.js
@@ -19,7 +19,6 @@ import { readOnly, reads } from "@ember/object/computed";
import { SKIP } from "discourse/lib/autocomplete";
import { Promise } from "rsvp";
import { translations } from "pretty-text/emoji/data";
-import { channelStatusName } from "discourse/plugins/chat/discourse/models/chat-channel";
import { setupHashtagAutocomplete } from "discourse/lib/hashtag-autocomplete";
import {
chatComposerButtons,
@@ -566,17 +565,21 @@ export default Component.extend(TextareaTextManipulation, {
@discourseComputed("userSilenced", "chatChannel.{chatable.users.[],id}")
placeholder(userSilenced, chatChannel) {
if (!chatChannel.canModifyMessages(this.currentUser)) {
- return I18n.t("chat.placeholder_new_message_disallowed", {
- status: channelStatusName(chatChannel.status).toLowerCase(),
- });
+ return I18n.t(
+ `chat.placeholder_new_message_disallowed.${chatChannel.status}`
+ );
}
if (chatChannel.isDraft) {
- return I18n.t("chat.placeholder_start_conversation", {
- usernames: chatChannel?.chatable?.users?.length
- ? chatChannel.chatable.users.mapBy("username").join(", ")
- : "...",
- });
+ if (chatChannel?.chatable?.users?.length) {
+ return I18n.t("chat.placeholder_start_conversation_users", {
+ usernames: chatChannel.chatable.users
+ .mapBy("username")
+ .join(I18n.t("word_connector.comma")),
+ });
+ } else {
+ return I18n.t("chat.placeholder_start_conversation");
+ }
}
if (userSilenced) {
@@ -596,14 +599,14 @@ export default Component.extend(TextareaTextManipulation, {
return I18n.t("chat.placeholder_self");
}
- return I18n.t("chat.placeholder_others", {
- messageRecipient: directMessageRecipients
+ return I18n.t("chat.placeholder_users", {
+ commaSeparatedNames: directMessageRecipients
.map((u) => u.name || `@${u.username}`)
- .join(", "),
+ .join(I18n.t("word_connector.comma")),
});
} else {
- return I18n.t("chat.placeholder_others", {
- messageRecipient: `#${chatChannel.title}`,
+ return I18n.t("chat.placeholder_channel", {
+ channelName: `#${chatChannel.title}`,
});
}
},
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-mention-warnings.js b/plugins/chat/assets/javascripts/discourse/components/chat-mention-warnings.js
index 8ea0880fab2..24592fec121 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-mention-warnings.js
+++ b/plugins/chat/assets/javascripts/discourse/components/chat-mention-warnings.js
@@ -2,6 +2,7 @@ import Component from "@glimmer/component";
import I18n from "I18n";
import { htmlSafe } from "@ember/template";
import { inject as service } from "@ember/service";
+import getURL from "discourse-common/lib/get-url";
export default class ChatMentionWarnings extends Component {
@service siteSettings;
@@ -79,31 +80,22 @@ export default class ChatMentionWarnings extends Component {
return;
}
- let notificationLimit = I18n.t(
- "chat.mention_warning.groups.notification_limit"
- );
-
- if (this.currentUser.staff) {
- notificationLimit = htmlSafe(
- `
- ${notificationLimit}
- `
+ if (this.currentUser.admin) {
+ return htmlSafe(
+ I18n.t("chat.mention_warning.too_many_mentions_admin", {
+ count: this.siteSettings.max_mentions_per_chat_message,
+ siteSettingUrl: getURL(
+ "/admin/site_settings/category/plugins?filter=max_mentions_per_chat_message"
+ ),
+ })
+ );
+ } else {
+ return htmlSafe(
+ I18n.t("chat.mention_warning.too_many_mentions", {
+ count: this.siteSettings.max_mentions_per_chat_message,
+ })
);
}
-
- const settingLimit = I18n.t("chat.mention_warning.mentions_limit", {
- count: this.siteSettings.max_mentions_per_chat_message,
- });
-
- return htmlSafe(
- I18n.t("chat.mention_warning.too_many_mentions", {
- notification_limit: notificationLimit,
- limit: settingLimit,
- })
- );
}
get unreachableBody() {
@@ -111,17 +103,21 @@ export default class ChatMentionWarnings extends Component {
return;
}
- if (this.unreachableGroupMentionsCount <= 2) {
- return I18n.t("chat.mention_warning.groups.unreachable", {
- group: this.unreachableGroupMentions[0],
- group_2: this.unreachableGroupMentions[1],
- count: this.unreachableGroupMentionsCount,
- });
- } else {
- return I18n.t("chat.mention_warning.groups.unreachable_multiple", {
- group: this.unreachableGroupMentions[0],
- count: this.unreachableGroupMentionsCount - 1, //N others
- });
+ switch (this.unreachableGroupMentionsCount) {
+ case 1:
+ return I18n.t("chat.mention_warning.groups.unreachable_1", {
+ group: this.unreachableGroupMentions[0],
+ });
+ case 2:
+ return I18n.t("chat.mention_warning.groups.unreachable_2", {
+ group1: this.unreachableGroupMentions[0],
+ group2: this.unreachableGroupMentions[1],
+ });
+ default:
+ return I18n.t("chat.mention_warning.groups.unreachable_multiple", {
+ group: this.unreachableGroupMentions[0],
+ count: this.unreachableGroupMentionsCount - 1,
+ });
}
}
@@ -130,44 +126,18 @@ export default class ChatMentionWarnings extends Component {
return;
}
- let notificationLimit = I18n.t(
- "chat.mention_warning.groups.notification_limit"
+ return htmlSafe(
+ I18n.messageFormat("chat.mention_warning.groups.too_many_members_MF", {
+ groupCount: this.overMembersLimitMentionsCount,
+ isAdmin: this.currentUser.admin,
+ siteSettingUrl: getURL(
+ "/admin/site_settings/category/plugins?filter=max_users_notified_per_group_mention"
+ ),
+ notificationLimit:
+ this.siteSettings.max_users_notified_per_group_mention,
+ group1: this.overMembersLimitGroupMentions[0],
+ group2: this.overMembersLimitGroupMentions[1],
+ })
);
-
- if (this.currentUser.staff) {
- notificationLimit = htmlSafe(
- `
- ${notificationLimit}
- `
- );
- }
-
- const settingLimit = I18n.t("chat.mention_warning.groups.users_limit", {
- count: this.siteSettings.max_users_notified_per_group_mention,
- });
-
- if (this.hasOverMembersLimitGroupMentions <= 2) {
- return htmlSafe(
- I18n.t("chat.mention_warning.groups.too_many_members", {
- group: this.overMembersLimitGroupMentions[0],
- group_2: this.overMembersLimitGroupMentions[1],
- count: this.overMembersLimitMentionsCount,
- notification_limit: notificationLimit,
- limit: settingLimit,
- })
- );
- } else {
- return htmlSafe(
- I18n.t("chat.mention_warning.groups.too_many_members_multiple", {
- group: this.overMembersLimitGroupMentions[0],
- count: this.overMembersLimitMentionsCount - 1, //N others
- notification_limit: notificationLimit,
- limit: settingLimit,
- })
- );
- }
}
}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-message-reaction.js b/plugins/chat/assets/javascripts/discourse/components/chat-message-reaction.js
index a15cdc06b73..748143d2ea3 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-message-reaction.js
+++ b/plugins/chat/assets/javascripts/discourse/components/chat-message-reaction.js
@@ -83,37 +83,91 @@ export default class ChatMessageReaction extends Component {
@computed("reaction")
get popoverContent() {
- let usernames = this.reaction.users.mapBy("username").join(", ");
- if (this.reaction.reacted) {
- if (this.reaction.count === 1) {
- return I18n.t("chat.reactions.only_you", {
- emoji: this.reaction.emoji,
- });
- } else if (this.reaction.count > 1 && this.reaction.count < 6) {
- return I18n.t("chat.reactions.and_others", {
- usernames,
- emoji: this.reaction.emoji,
- });
- } else if (this.reaction.count >= 6) {
- return I18n.t("chat.reactions.you_others_and_more", {
- usernames,
- emoji: this.reaction.emoji,
- more: this.reaction.count - 5,
- });
- }
- } else {
- if (this.reaction.count > 0 && this.reaction.count < 6) {
- return I18n.t("chat.reactions.only_others", {
- usernames,
- emoji: this.reaction.emoji,
- });
- } else if (this.reaction.count >= 6) {
- return I18n.t("chat.reactions.others_and_more", {
- usernames,
- emoji: this.reaction.emoji,
- more: this.reaction.count - 5,
- });
- }
+ return this.reaction.reacted
+ ? this._reactionTextWithSelf()
+ : this._reactionText();
+ }
+
+ _reactionTextWithSelf() {
+ const reactionCount = this.reaction.count;
+
+ if (reactionCount === 0) {
+ return;
}
+
+ if (reactionCount === 1) {
+ return I18n.t("chat.reactions.only_you", {
+ emoji: this.reaction.emoji,
+ });
+ }
+
+ const maxUsernames = 4;
+ const usernames = this.reaction.users
+ .slice(0, maxUsernames)
+ .mapBy("username");
+
+ if (reactionCount === 2) {
+ return I18n.t("chat.reactions.you_and_single_user", {
+ emoji: this.reaction.emoji,
+ username: usernames.pop(),
+ });
+ }
+
+ // `-1` because the current user ("you") isn't included in `usernames`
+ const unnamedUserCount = reactionCount - usernames.length - 1;
+
+ if (unnamedUserCount > 0) {
+ return I18n.t("chat.reactions.you_multiple_users_and_more", {
+ emoji: this.reaction.emoji,
+ commaSeparatedUsernames: this._joinUsernames(usernames),
+ count: unnamedUserCount,
+ });
+ }
+
+ return I18n.t("chat.reactions.you_and_multiple_users", {
+ emoji: this.reaction.emoji,
+ username: usernames.pop(),
+ commaSeparatedUsernames: this._joinUsernames(usernames),
+ });
+ }
+
+ _reactionText() {
+ const reactionCount = this.reaction.count;
+
+ if (reactionCount === 0) {
+ return;
+ }
+
+ const maxUsernames = 5;
+ const usernames = this.reaction.users
+ .slice(0, maxUsernames)
+ .mapBy("username");
+
+ if (reactionCount === 1) {
+ return I18n.t("chat.reactions.single_user", {
+ emoji: this.reaction.emoji,
+ username: usernames.pop(),
+ });
+ }
+
+ const unnamedUserCount = reactionCount - usernames.length;
+
+ if (unnamedUserCount > 0) {
+ return I18n.t("chat.reactions.multiple_users_and_more", {
+ emoji: this.reaction.emoji,
+ commaSeparatedUsernames: this._joinUsernames(usernames),
+ count: unnamedUserCount,
+ });
+ }
+
+ return I18n.t("chat.reactions.multiple_users", {
+ emoji: this.reaction.emoji,
+ username: usernames.pop(),
+ commaSeparatedUsernames: this._joinUsernames(usernames),
+ });
+ }
+
+ _joinUsernames(usernames) {
+ return usernames.join(I18n.t("word_connector.comma"));
}
}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-message.js b/plugins/chat/assets/javascripts/discourse/components/chat-message.js
index 1931f97db37..a8865c36510 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-message.js
+++ b/plugins/chat/assets/javascripts/discourse/components/chat-message.js
@@ -411,49 +411,53 @@ export default class ChatMessage extends Component {
}
get mentionedCannotSeeText() {
- return I18n.t("chat.mention_warning.cannot_see", {
- username: this.mentionWarning?.cannot_see?.[0]?.username,
- count: this.mentionWarning?.cannot_see?.length,
- others: this._othersTranslation(
- this.mentionWarning?.cannot_see?.length - 1
- ),
- });
+ return this._findTranslatedWarning(
+ "chat.mention_warning.cannot_see",
+ "chat.mention_warning.cannot_see_multiple",
+ {
+ username: this.mentionWarning?.cannot_see?.[0]?.username,
+ count: this.mentionWarning?.cannot_see?.length,
+ }
+ );
}
get mentionedWithoutMembershipText() {
- return I18n.t("chat.mention_warning.without_membership", {
- username: this.mentionWarning?.without_membership?.[0]?.username,
- count: this.mentionWarning?.without_membership?.length,
- others: this._othersTranslation(
- this.mentionWarning?.without_membership?.length - 1
- ),
- });
+ return this._findTranslatedWarning(
+ "chat.mention_warning.without_membership",
+ "chat.mention_warning.without_membership_multiple",
+ {
+ username: this.mentionWarning?.without_membership?.[0]?.username,
+ count: this.mentionWarning?.without_membership?.length,
+ }
+ );
}
get groupsWithDisabledMentions() {
- return I18n.t("chat.mention_warning.group_mentions_disabled", {
- group_name: this.mentionWarning?.group_mentions_disabled?.[0],
- count: this.mentionWarning?.group_mentions_disabled?.length,
- others: this._othersTranslation(
- this.mentionWarning?.group_mentions_disabled?.length - 1
- ),
- });
+ return this._findTranslatedWarning(
+ "chat.mention_warning.group_mentions_disabled",
+ "chat.mention_warning.group_mentions_disabled_multiple",
+ {
+ group_name: this.mentionWarning?.group_mentions_disabled?.[0],
+ count: this.mentionWarning?.group_mentions_disabled?.length,
+ }
+ );
}
get groupsWithTooManyMembers() {
- return I18n.t("chat.mention_warning.too_many_members", {
- group_name: this.mentionWarning.groups_with_too_many_members?.[0],
- count: this.mentionWarning.groups_with_too_many_members?.length,
- others: this._othersTranslation(
- this.mentionWarning.groups_with_too_many_members?.length - 1
- ),
- });
+ return this._findTranslatedWarning(
+ "chat.mention_warning.too_many_members",
+ "chat.mention_warning.too_many_members_multiple",
+ {
+ group_name: this.mentionWarning.groups_with_too_many_members?.[0],
+ count: this.mentionWarning.groups_with_too_many_members?.length,
+ }
+ );
}
- _othersTranslation(othersCount) {
- return I18n.t("chat.mention_warning.warning_multiple", {
- count: othersCount,
- });
+ _findTranslatedWarning(oneKey, multipleKey, args) {
+ const translationKey = args.count === 1 ? oneKey : multipleKey;
+ args.count--;
+ return I18n.t(translationKey, args);
}
@action
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-replying-indicator.js b/plugins/chat/assets/javascripts/discourse/components/chat-replying-indicator.js
index 0e0f797e938..6c46c2e9101 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-replying-indicator.js
+++ b/plugins/chat/assets/javascripts/discourse/components/chat-replying-indicator.js
@@ -33,14 +33,18 @@ export default Component.extend({
if (usernames.length < 4) {
const lastUsername = usernames.pop();
- const commaSeparatedUsernames = usernames.join(", ");
+ const commaSeparatedUsernames = usernames.join(
+ I18n.t("word_connector.comma")
+ );
return I18n.t("chat.replying_indicator.multiple_users", {
commaSeparatedUsernames,
lastUsername,
});
}
- const commaSeparatedUsernames = usernames.slice(0, 2).join(", ");
+ const commaSeparatedUsernames = usernames
+ .slice(0, 2)
+ .join(I18n.t("word_connector.comma"));
return I18n.t("chat.replying_indicator.many_users", {
commaSeparatedUsernames,
count: usernames.length - 2,
diff --git a/plugins/chat/assets/javascripts/discourse/controllers/create-channel.js b/plugins/chat/assets/javascripts/discourse/controllers/create-channel.js
index 0b6328bd886..0f0079de005 100644
--- a/plugins/chat/assets/javascripts/discourse/controllers/create-channel.js
+++ b/plugins/chat/assets/javascripts/discourse/controllers/create-channel.js
@@ -103,20 +103,40 @@ export default class CreateChannelController extends Controller.extend(
_updateAutoJoinConfirmWarning(category, catPermissions) {
const allowedGroups = catPermissions.allowed_groups;
+ let warning;
if (catPermissions.private) {
- const warningTranslationKey =
- allowedGroups.length < 3 ? "warning_groups" : "warning_multiple_groups";
-
- this.set(
- "autoJoinWarning",
- I18n.t(`chat.create_channel.auto_join_users.${warningTranslationKey}`, {
- members_count: catPermissions.members_count,
- group: escapeExpression(allowedGroups[0]),
- group_2: escapeExpression(allowedGroups[1]),
- count: allowedGroups.length,
- })
- );
+ switch (allowedGroups.length) {
+ case 1:
+ warning = I18n.t(
+ "chat.create_channel.auto_join_users.warning_1_group",
+ {
+ count: catPermissions.members_count,
+ group: escapeExpression(allowedGroups[0]),
+ }
+ );
+ break;
+ case 2:
+ warning = I18n.t(
+ "chat.create_channel.auto_join_users.warning_2_groups",
+ {
+ count: catPermissions.members_count,
+ group1: escapeExpression(allowedGroups[0]),
+ group2: escapeExpression(allowedGroups[1]),
+ }
+ );
+ break;
+ default:
+ warning = I18n.messageFormat(
+ "chat.create_channel.auto_join_users.warning_multiple_groups_MF",
+ {
+ groupCount: allowedGroups.length - 1,
+ userCount: catPermissions.members_count,
+ groupName: escapeExpression(allowedGroups[0]),
+ }
+ );
+ break;
+ }
} else {
this.set(
"autoJoinWarning",
@@ -125,6 +145,8 @@ export default class CreateChannelController extends Controller.extend(
})
);
}
+
+ this.set("autoJoinWarning", warning);
}
_updatePermissionsHint(category) {
@@ -136,20 +158,42 @@ export default class CreateChannelController extends Controller.extend(
.then((catPermissions) => {
this._updateAutoJoinConfirmWarning(category, catPermissions);
const allowedGroups = catPermissions.allowed_groups;
- const translationKey =
- allowedGroups.length < 3 ? "hint_groups" : "hint_multiple_groups";
+ const settingLink = `/c/${escapeExpression(fullSlug)}/edit/security`;
+ let hint;
- this.set(
- "categoryPermissionsHint",
- htmlSafe(
- I18n.t(`chat.create_channel.choose_category.${translationKey}`, {
- link: `/c/${escapeExpression(fullSlug)}/edit/security`,
- hint: escapeExpression(allowedGroups[0]),
- hint_2: escapeExpression(allowedGroups[1]),
- count: allowedGroups.length,
- })
- )
- );
+ switch (allowedGroups.length) {
+ case 1:
+ hint = I18n.t(
+ "chat.create_channel.choose_category.hint_1_group",
+ {
+ settingLink,
+ group: escapeExpression(allowedGroups[0]),
+ }
+ );
+ break;
+ case 2:
+ hint = I18n.t(
+ "chat.create_channel.choose_category.hint_2_groups",
+ {
+ settingLink,
+ group1: escapeExpression(allowedGroups[0]),
+ group2: escapeExpression(allowedGroups[1]),
+ }
+ );
+ break;
+ default:
+ hint = I18n.t(
+ "chat.create_channel.choose_category.hint_multiple_groups",
+ {
+ settingLink,
+ group: escapeExpression(allowedGroups[0]),
+ count: allowedGroups.length - 1,
+ }
+ );
+ break;
+ }
+
+ this.set("categoryPermissionsHint", htmlSafe(hint));
});
} else {
this.set("categoryPermissionsHint", DEFAULT_HINT);
diff --git a/plugins/chat/assets/javascripts/discourse/initializers/chat-sidebar.js b/plugins/chat/assets/javascripts/discourse/initializers/chat-sidebar.js
index 1cb408dbaba..56fff731a30 100644
--- a/plugins/chat/assets/javascripts/discourse/initializers/chat-sidebar.js
+++ b/plugins/chat/assets/javascripts/discourse/initializers/chat-sidebar.js
@@ -223,8 +223,8 @@ export default {
}
get title() {
- return I18n.t("chat.placeholder_others", {
- messageRecipient: this.channel.escapedTitle,
+ return I18n.t("chat.placeholder_channel", {
+ channelName: this.channel.escapedTitle,
});
}
diff --git a/plugins/chat/assets/javascripts/discourse/models/chat-channel.js b/plugins/chat/assets/javascripts/discourse/models/chat-channel.js
index c38b83d5650..c6e75e9edd3 100644
--- a/plugins/chat/assets/javascripts/discourse/models/chat-channel.js
+++ b/plugins/chat/assets/javascripts/discourse/models/chat-channel.js
@@ -1,5 +1,4 @@
import RestModel from "discourse/models/rest";
-import I18n from "I18n";
import User from "discourse/models/user";
import UserChatChannelMembership from "discourse/plugins/chat/discourse/models/user-chat-channel-membership";
import { ajax } from "discourse/lib/ajax";
@@ -21,19 +20,6 @@ export const CHANNEL_STATUSES = {
archived: "archived",
};
-export function channelStatusName(channelStatus) {
- switch (channelStatus) {
- case CHANNEL_STATUSES.open:
- return I18n.t("chat.channel_status.open");
- case CHANNEL_STATUSES.readOnly:
- return I18n.t("chat.channel_status.read_only");
- case CHANNEL_STATUSES.closed:
- return I18n.t("chat.channel_status.closed");
- case CHANNEL_STATUSES.archived:
- return I18n.t("chat.channel_status.archived");
- }
-}
-
export function channelStatusIcon(channelStatus) {
if (channelStatus === CHANNEL_STATUSES.open) {
return null;
diff --git a/plugins/chat/config/locales/client.en.yml b/plugins/chat/config/locales/client.en.yml
index 87a89e3dd3d..d3d47e6f853 100644
--- a/plugins/chat/config/locales/client.en.yml
+++ b/plugins/chat/config/locales/client.en.yml
@@ -106,46 +106,96 @@ en:
new_messages: "new messages"
mention_warning:
dismiss: "dismiss"
- cannot_see:
- one: "%{username} cannot access this channel and was not notified."
- other: "%{username} and %{others} cannot access this channel and were not notified."
+ cannot_see: "%{username} can't access this channel and was not notified."
+ cannot_see_multiple:
+ one: "%{username} and %{count} other user cannot access this channel and were not notified."
+ other: "%{username} and %{count} other users cannot access this channel and were not notified."
invitations_sent:
one: "Invitation sent"
other: "Invitations sent"
invite: "Invite to channel"
- without_membership:
- one: "%{username} has not joined this channel."
- other: "%{username} and %{others} have not joined this channel."
- group_mentions_disabled:
- one: "%{group_name} doesn't allow mentions"
- other: "%{group_name} and %{others} doesn't allow mentions"
- too_many_members:
- one: "%{group_name} has too many members. No one was notified"
- other: "%{group_name} and %{others} have too many members. No one was notified"
- warning_multiple:
- one: "%{count} other"
- other: "%{count} others"
-
+ without_membership: "%{username} has not joined this channel."
+ without_membership_multiple:
+ one: "%{username} and %{count} other user have not joined this channel."
+ other: "%{username} and %{count} other users have not joined this channel."
+ group_mentions_disabled: "%{group_name} doesn't allow mentions."
+ group_mentions_disabled_multiple:
+ one: "%{group_name} and %{count} other group don't allow mentions."
+ other: "%{group_name} and %{count} other groups don't allow mentions."
+ too_many_members: "%{group_name} has too many members. No one was notified."
+ too_many_members_multiple:
+ one: "%{group_name} and %{count} other group have too many members. No one was notified."
+ other: "%{group_name} and %{count} other groups have too many members. No one was notified."
groups:
header:
some: "Some users won't be notified"
all: "Nobody will be notified"
- unreachable:
- one: "@%{group} doesn't allow mentions"
- other: "@%{group} and @%{group_2} doesn't allow mentions"
- unreachable_multiple: "@%{group} and %{count} others doesn't allow mentions"
- too_many_members:
- one: "Mentioning @%{group} exceeds the %{notification_limit} of %{limit}"
- other: "Mentioning both @%{group} or @%{group_2} exceeds the %{notification_limit} of %{limit}"
- too_many_members_multiple: "These %{count} groups exceed the %{notification_limit} of %{limit}"
- users_limit:
- one: "%{count} user"
- other: "%{count} users"
- notification_limit: "notification limit"
- too_many_mentions: "This message exceeds the %{notification_limit} of %{limit}"
- mentions_limit:
- one: "%{count} mention"
- other: "%{count} mentions"
+ unreachable_1: "@%{group} doesn't allow mentions."
+ unreachable_2: "@%{group1} and @%{group2} don't allow mentions."
+ unreachable_multiple:
+ one: "@%{group} and %{count} other group don't allow mentions."
+ other: "@%{group} and %{count} other groups don't allow mentions."
+ too_many_members_MF: |
+ { groupCount, plural,
+ =1 {
+ { isAdmin, select,
+ true {
+ { notificationLimit, plural,
+ one {Mentioning @{group1} exceeds the notification limit of # user.}
+ other {Mentioning @{group1} exceeds the notification limit of # users.}
+ }
+ }
+ false {
+ { notificationLimit, plural,
+ one {Mentioning @{group1} exceeds the notification limit of # user.}
+ other {Mentioning @{group1} exceeds the notification limit of # users.}
+ }
+ }
+ other {}
+ }
+ }
+ =2 {
+ { isAdmin, select,
+ true {
+ { notificationLimit, plural,
+ one {Mentioning @{group1} and @{group2} exceeds the notification limit of # user.}
+ other {Mentioning @{group1} and @{group2} exceeds the notification limit of # users.}
+ }
+ }
+ false {
+ { notificationLimit, plural,
+ one {Mentioning @{group1} and @{group2} exceeds the notification limit of # user.}
+ other {Mentioning @{group1} and @{group2} exceeds the notification limit of # users.}
+ }
+ }
+ other {}
+ }
+ }
+ other {
+ { isAdmin, select,
+ true {
+ { notificationLimit, plural,
+ one {Mentioning these {groupCount} groups exceeds the notification limit of # user.}
+ other {Mentioning these {groupCount} groups exceeds the notification limit of # users.}
+ }
+ }
+ false {
+ { notificationLimit, plural,
+ one {Mentioning these {groupCount} groups exceeds the notification limit of # user.}
+ other {Mentioning these {groupCount} groups exceeds the notification limit of # users.}
+ }
+ }
+ other {}
+ }
+ }
+ }
+ too_many_mentions:
+ one: "This message exceeds the notification limit of %{count} mention."
+ other: "This message exceeds the notification limit of %{count} mentions."
+ too_many_mentions_admin:
+ one: 'This message exceeds the notification limit of %{count} mention.'
+ other: 'This message exceeds the notification limit of %{count} mentions.'
+
aria_roles:
header: "Chat header"
composer: "Chat composer"
@@ -163,10 +213,15 @@ en:
close_full_page: "Close full-screen chat"
open_message: "Open message in chat"
placeholder_self: "Jot something down"
- placeholder_others: "Chat with %{messageRecipient}"
- placeholder_new_message_disallowed: "Channel is %{status}, you cannot send new messages right now."
+ placeholder_channel: "Chat with %{channelName}"
+ placeholder_users: "Chat with %{commaSeparatedNames}"
+ placeholder_new_message_disallowed:
+ archived: "Channel is archived, you cannot send new messages right now."
+ closed: "Channel is closed, you cannot send new messages right now."
+ read_only: "Channel is read only, you cannot send new messages right now."
placeholder_silenced: "You cannot send messages at this time."
- placeholder_start_conversation: Start a conversation with %{usernames}
+ placeholder_start_conversation: "Start a conversation with ..."
+ placeholder_start_conversation_users: "Start a conversation with %{commaSeparatedUsernames}"
remove_upload: "Remove file"
react: "React with emoji"
reply: "Reply"
@@ -276,18 +331,36 @@ en:
create_channel:
auto_join_users:
public_category_warning: "%{category} is a public category. Automatically add all recently active users to this channel?"
- warning_groups:
- one: Automatically add %{members_count} users from %{group}?
- other: Automatically add %{members_count} users from %{group} and %{group_2}?
- warning_multiple_groups: Automatically add %{members_count} users from %{group_1} and %{count} others?
+ warning_1_group:
+ one: "Automatically add %{count} user from %{group}?"
+ other: "Automatically add %{count} users from %{group}?"
+ warning_2_groups:
+ one: "Automatically add %{count} user from %{group1} and %{group2}?"
+ other: "Automatically add %{count} users from %{group1} and %{group2}?"
+ warning_multiple_groups_MF: |
+ { groupCount, plural,
+ one {
+ { userCount, plural,
+ one {Automatically add {userCount} user from {groupName} and {groupCount} other group?}
+ other {Automatically add {userCount} users from {groupName} and {groupCount} other group?}
+ }
+ }
+ other {
+ { userCount, plural,
+ one {Automatically add {userCount} user from {groupName} and {groupCount} other groups?}
+ other {Automatically add {userCount} users from {groupName} and {groupCount} other groups?}
+ }
+ }
+ }
choose_category:
label: "Choose a category"
none: "select one..."
default_hint: Manage access by visiting %{category} security settings
- hint_groups:
- one: Users in %{hint} will have access to this channel per the security settings
- other: Users in %{hint} and %{hint_2} will have access to this channel per the security settings
- hint_multiple_groups: Users in %{hint_1} and %{count} other groups will have access to this channel per the security settings
+ hint_1_group: 'Users in %{group} will have access to this channel per the security settings'
+ hint_2_groups: 'Users in %{group1} and %{group2} will have access to this channel per the security settings'
+ hint_multiple_groups:
+ one: 'Users in %{group} and %{count} other group will have access to this channel per the security settings'
+ other: 'Users in %{group} and %{count} other groups will have access to this channel per the security settings'
create: "Create channel"
description: "Description (optional)"
name: "Channel name"
@@ -303,10 +376,16 @@ en:
reactions:
only_you: "You reacted with :%{emoji}:"
- and_others: "You, %{usernames} reacted with :%{emoji}:"
- only_others: "%{usernames} reacted with :%{emoji}:"
- others_and_more: "%{usernames} and %{more} others reacted with :%{emoji}:"
- you_others_and_more: "You, %{usernames} and %{more} others reacted with :%{emoji}:"
+ you_and_single_user: "You and %{username} reacted with :%{emoji}:"
+ you_and_multiple_users: "You, %{commaSeparatedUsernames} and %{username} reacted with :%{emoji}:"
+ you_multiple_users_and_more:
+ one: "You, %{commaSeparatedUsernames} and %{count} other reacted with :%{emoji}:"
+ other: "You, %{commaSeparatedUsernames} and %{count} others reacted with :%{emoji}:"
+ single_user: "%{username} reacted with :%{emoji}:"
+ multiple_users: "%{commaSeparatedUsernames} and %{username} reacted with :%{emoji}:"
+ multiple_users_and_more:
+ one: "%{commaSeparatedUsernames} and %{count} other reacted with :%{emoji}:"
+ other: "%{commaSeparatedUsernames} and %{count} others reacted with :%{emoji}:"
composer:
toggle_toolbar: "Toggle toolbar"
@@ -465,11 +544,13 @@ en:
direct: 'mentioned you in "%{channel}"'
direct_html: '%{username} mentioned you in "%{channel}"'
other_plain: 'mentioned %{identifier} in "%{channel}"'
+ # %{identifier} is either @here or @all
other_html: '%{username} mentioned %{identifier} in "%{channel}"'
direct_message_chat_mention:
direct: "mentioned you in personal chat"
direct_html: "%{username} mentioned you in personal chat"
other_plain: "mentioned %{identifier} in personal chat"
+ # %{identifier} is either @here or @all
other_html: "%{username} mentioned %{identifier} in personal chat"
chat_message: "New chat message"
chat_quoted: "%{username} quoted your chat message"
diff --git a/plugins/chat/config/locales/server.en.yml b/plugins/chat/config/locales/server.en.yml
index 89142083fbf..b6b312d6c53 100644
--- a/plugins/chat/config/locales/server.en.yml
+++ b/plugins/chat/config/locales/server.en.yml
@@ -49,16 +49,26 @@ en:
deleted_chat_username: deleted
errors:
channel_exists_for_category: "A channel already exists for this category and name"
- channel_new_message_disallowed: "The channel is %{status}, no new messages can be sent"
- channel_modify_message_disallowed: "The channel is %{status}, no messages can be edited or deleted"
+ channel_new_message_disallowed:
+ archived: "The channel is archived, no new messages can be sent"
+ closed: "The channel is closed, no new messages can be sent"
+ read_only: "The channel is read only, no new messages can be sent"
+ channel_modify_message_disallowed:
+ archived: "The channel is archived, no messages can be edited or deleted"
+ closed: "The channel is closed, no messages can be edited or deleted"
+ read_only: "The channel is read only, no messages can be edited or deleted"
user_cannot_send_message: "You cannot send messages at this time."
rate_limit_exceeded: "Exceeded the limit of chat messages that can be sent within 30 seconds"
auto_silence_from_flags: "Chat message flagged with score high enough to silence user."
channel_cannot_be_archived: "The channel cannot be archived at this time, it must be either closed or open to archive."
duplicate_message: "You posted an identical message too recently."
delete_channel_failed: "Delete channel failed, please try again."
- minimum_length_not_met: "Message is too short, must have a minimum of %{minimum} characters."
- message_too_long: "Message is too long, messages must be a maximum of %{maximum} characters."
+ minimum_length_not_met:
+ one: "Message is too short, must have a minimum of %{count} character."
+ other: "Message is too short, must have a minimum of %{count} characters."
+ message_too_long:
+ one: "Message is too long, messages must be a maximum of %{count} characters."
+ other: "Message is too long, messages must be a maximum of %{count} characters."
draft_too_long: "Draft is too long."
max_reactions_limit_reached: "New reactions are not allowed on this message."
message_move_invalid_channel: "The source and destination channel must be public channels."
@@ -70,8 +80,9 @@ en:
actor_disallowed_dms: "You have chosen to prevent users from sending you private and direct messages, so you cannot create new direct messages."
actor_preventing_target_user_from_dm: "You have chosen to prevent %{username} from sending you private and direct messages, so you cannot create new direct messages to them."
user_cannot_send_direct_messages: "Sorry, you cannot send direct messages."
+ over_chat_max_direct_message_users_allow_self: "You can only create a direct message with yourself."
over_chat_max_direct_message_users:
- one: "You can only create a direct message with yourself."
+ one: "You can't create a direct message with more than %{count} other user."
other: "You can't create a direct message with more than %{count} other users."
original_message_not_found: "The ancestor of the message you are replying cannot be found or has been deleted."
reviewables:
@@ -110,20 +121,17 @@ en:
transcript_title: "Transcript of previous messages in %{channel_name}"
transcript_body: "To give you more context, we included a transcript of the previous messages in this conversation (up to ten):\n\n%{transcript}"
channel:
- statuses:
- read_only: "Read Only"
- archived: "Archived"
- closed: "Closed"
- open: "Open"
archive:
first_post_raw: "This topic is an archive of the [%{channel_name}](%{channel_url}) chat channel."
messages_moved:
one: "@%{acting_username} moved a message to the [%{channel_name}](%{first_moved_message_url}) channel."
other: "@%{acting_username} moved %{count} messages to the [%{channel_name}](%{first_moved_message_url}) channel."
dm_title:
- single_user: "%{user}"
- multi_user: "%{users}"
- multi_user_truncated: "%{users} and %{leftover} others"
+ single_user: "%{username}"
+ multi_user: "%{comma_separated_usernames}"
+ multi_user_truncated:
+ one: "%{comma_separated_usernames} and %{count} other"
+ other: "%{comma_separated_usernames} and %{count} others"
category_channel:
errors:
diff --git a/plugins/chat/lib/chat_message_creator.rb b/plugins/chat/lib/chat_message_creator.rb
index 08b5a711a08..6cd55f2fedb 100644
--- a/plugins/chat/lib/chat_message_creator.rb
+++ b/plugins/chat/lib/chat_message_creator.rb
@@ -82,10 +82,7 @@ class Chat::ChatMessageCreator
raise StandardError.new(I18n.t("chat.errors.user_cannot_send_direct_messages"))
else
raise StandardError.new(
- I18n.t(
- "chat.errors.channel_new_message_disallowed",
- status: @chat_channel.status_name,
- ),
+ I18n.t("chat.errors.channel_new_message_disallowed.#{@chat_channel.status}"),
)
end
end
diff --git a/plugins/chat/lib/chat_message_reactor.rb b/plugins/chat/lib/chat_message_reactor.rb
index 9e7260f7979..8815fa135e3 100644
--- a/plugins/chat/lib/chat_message_reactor.rb
+++ b/plugins/chat/lib/chat_message_reactor.rb
@@ -53,10 +53,7 @@ class Chat::ChatMessageReactor
raise Discourse::InvalidAccess.new(
nil,
nil,
- custom_message: "chat.errors.channel_modify_message_disallowed",
- custom_message_params: {
- status: @chat_channel.status_name,
- },
+ custom_message: "chat.errors.channel_modify_message_disallowed.#{@chat_channel.status}",
)
end
diff --git a/plugins/chat/lib/chat_message_updater.rb b/plugins/chat/lib/chat_message_updater.rb
index 79ecfed4e2c..43bb028c40d 100644
--- a/plugins/chat/lib/chat_message_updater.rb
+++ b/plugins/chat/lib/chat_message_updater.rb
@@ -51,10 +51,7 @@ class Chat::ChatMessageUpdater
def validate_channel_status!
return if @guardian.can_modify_channel_message?(@chat_channel)
raise StandardError.new(
- I18n.t(
- "chat.errors.channel_modify_message_disallowed",
- status: @chat_channel.status_name,
- ),
+ I18n.t("chat.errors.channel_modify_message_disallowed.#{@chat_channel.status}"),
)
end
diff --git a/plugins/chat/lib/direct_message_channel_creator.rb b/plugins/chat/lib/direct_message_channel_creator.rb
index 63342e3cfb7..505801d42fe 100644
--- a/plugins/chat/lib/direct_message_channel_creator.rb
+++ b/plugins/chat/lib/direct_message_channel_creator.rb
@@ -30,12 +30,16 @@ module Chat::DirectMessageChannelCreator
target_users = target_users.reject { |user| user.id == acting_user.id }
if !acting_user.staff? && target_users.size > SiteSetting.chat_max_direct_message_users
- raise NotAllowed.new(
- I18n.t(
- "chat.errors.over_chat_max_direct_message_users",
- count: SiteSetting.chat_max_direct_message_users + 1, # +1 for the acting_user
- ),
- )
+ if SiteSetting.chat_max_direct_message_users == 0
+ raise NotAllowed.new(I18n.t("chat.errors.over_chat_max_direct_message_users_allow_self"))
+ else
+ raise NotAllowed.new(
+ I18n.t(
+ "chat.errors.over_chat_max_direct_message_users",
+ count: SiteSetting.chat_max_direct_message_users + 1, # +1 for the acting_user
+ ),
+ )
+ end
end
end
diff --git a/plugins/chat/spec/components/chat_message_creator_spec.rb b/plugins/chat/spec/components/chat_message_creator_spec.rb
index de4cf37173a..798149ece86 100644
--- a/plugins/chat/spec/components/chat_message_creator_spec.rb
+++ b/plugins/chat/spec/components/chat_message_creator_spec.rb
@@ -64,7 +64,7 @@ describe Chat::ChatMessageCreator do
expect(creator.error.message).to match(
I18n.t(
"chat.errors.minimum_length_not_met",
- { minimum: SiteSetting.chat_minimum_message_length },
+ { count: SiteSetting.chat_minimum_message_length },
),
)
end
@@ -79,10 +79,7 @@ describe Chat::ChatMessageCreator do
)
expect(creator.failed?).to eq(true)
expect(creator.error.message).to match(
- I18n.t(
- "chat.errors.message_too_long",
- { maximum: SiteSetting.chat_maximum_message_length },
- ),
+ I18n.t("chat.errors.message_too_long", { count: SiteSetting.chat_maximum_message_length }),
)
end
@@ -866,10 +863,7 @@ describe Chat::ChatMessageCreator do
creator = create_message(user1)
expect(creator.failed?).to eq(true)
expect(creator.error.message).to eq(
- I18n.t(
- "chat.errors.channel_new_message_disallowed",
- status: public_chat_channel.status_name,
- ),
+ I18n.t("chat.errors.channel_new_message_disallowed.closed"),
)
end
@@ -885,18 +879,12 @@ describe Chat::ChatMessageCreator do
creator = create_message(user1)
expect(creator.failed?).to eq(true)
expect(creator.error.message).to eq(
- I18n.t(
- "chat.errors.channel_new_message_disallowed",
- status: public_chat_channel.status_name,
- ),
+ I18n.t("chat.errors.channel_new_message_disallowed.read_only"),
)
creator = create_message(admin1)
expect(creator.failed?).to eq(true)
expect(creator.error.message).to eq(
- I18n.t(
- "chat.errors.channel_new_message_disallowed",
- status: public_chat_channel.status_name,
- ),
+ I18n.t("chat.errors.channel_new_message_disallowed.read_only"),
)
end
end
@@ -908,18 +896,12 @@ describe Chat::ChatMessageCreator do
creator = create_message(user1)
expect(creator.failed?).to eq(true)
expect(creator.error.message).to eq(
- I18n.t(
- "chat.errors.channel_new_message_disallowed",
- status: public_chat_channel.status_name,
- ),
+ I18n.t("chat.errors.channel_new_message_disallowed.archived"),
)
creator = create_message(admin1)
expect(creator.failed?).to eq(true)
expect(creator.error.message).to eq(
- I18n.t(
- "chat.errors.channel_new_message_disallowed",
- status: public_chat_channel.status_name,
- ),
+ I18n.t("chat.errors.channel_new_message_disallowed.archived"),
)
end
end
diff --git a/plugins/chat/spec/components/chat_message_updater_spec.rb b/plugins/chat/spec/components/chat_message_updater_spec.rb
index 39c00726bc6..62de1bd9e3f 100644
--- a/plugins/chat/spec/components/chat_message_updater_spec.rb
+++ b/plugins/chat/spec/components/chat_message_updater_spec.rb
@@ -62,7 +62,7 @@ describe Chat::ChatMessageUpdater do
expect(updater.error.message).to match(
I18n.t(
"chat.errors.minimum_length_not_met",
- { minimum: SiteSetting.chat_minimum_message_length },
+ { count: SiteSetting.chat_minimum_message_length },
),
)
expect(chat_message.reload.message).to eq(og_message)
@@ -82,7 +82,7 @@ describe Chat::ChatMessageUpdater do
)
expect(updater.failed?).to eq(true)
expect(updater.error.message).to match(
- I18n.t("chat.errors.message_too_long", { maximum: SiteSetting.chat_maximum_message_length }),
+ I18n.t("chat.errors.message_too_long", { count: SiteSetting.chat_maximum_message_length }),
)
expect(chat_message.reload.message).to eq(og_message)
end
@@ -528,10 +528,7 @@ describe Chat::ChatMessageUpdater do
updater = update_message(user1)
expect(updater.failed?).to eq(true)
expect(updater.error.message).to eq(
- I18n.t(
- "chat.errors.channel_modify_message_disallowed",
- status: public_chat_channel.status_name,
- ),
+ I18n.t("chat.errors.channel_modify_message_disallowed.closed"),
)
end
@@ -548,18 +545,12 @@ describe Chat::ChatMessageUpdater do
updater = update_message(user1)
expect(updater.failed?).to eq(true)
expect(updater.error.message).to eq(
- I18n.t(
- "chat.errors.channel_modify_message_disallowed",
- status: public_chat_channel.status_name,
- ),
+ I18n.t("chat.errors.channel_modify_message_disallowed.read_only"),
)
updater = update_message(admin1)
expect(updater.failed?).to eq(true)
expect(updater.error.message).to eq(
- I18n.t(
- "chat.errors.channel_modify_message_disallowed",
- status: public_chat_channel.status_name,
- ),
+ I18n.t("chat.errors.channel_modify_message_disallowed.read_only"),
)
end
end
@@ -571,18 +562,12 @@ describe Chat::ChatMessageUpdater do
updater = update_message(user1)
expect(updater.failed?).to eq(true)
expect(updater.error.message).to eq(
- I18n.t(
- "chat.errors.channel_modify_message_disallowed",
- status: public_chat_channel.status_name,
- ),
+ I18n.t("chat.errors.channel_modify_message_disallowed.archived"),
)
updater = update_message(admin1)
expect(updater.failed?).to eq(true)
expect(updater.error.message).to eq(
- I18n.t(
- "chat.errors.channel_modify_message_disallowed",
- status: public_chat_channel.status_name,
- ),
+ I18n.t("chat.errors.channel_modify_message_disallowed.archived"),
)
end
end
diff --git a/plugins/chat/spec/lib/direct_message_channel_creator_spec.rb b/plugins/chat/spec/lib/direct_message_channel_creator_spec.rb
index ff3863ca3a7..0ae71e0c462 100644
--- a/plugins/chat/spec/lib/direct_message_channel_creator_spec.rb
+++ b/plugins/chat/spec/lib/direct_message_channel_creator_spec.rb
@@ -212,7 +212,7 @@ describe Chat::DirectMessageChannelCreator do
subject.create!(acting_user: user_1, target_users: [user_1, user_2])
}.to raise_error(
Chat::DirectMessageChannelCreator::NotAllowed,
- I18n.t("chat.errors.over_chat_max_direct_message_users", count: 1),
+ I18n.t("chat.errors.over_chat_max_direct_message_users_allow_self"),
)
end
end
diff --git a/plugins/chat/spec/models/direct_message_spec.rb b/plugins/chat/spec/models/direct_message_spec.rb
index 9e44e51cd5d..8e8443cf90d 100644
--- a/plugins/chat/spec/models/direct_message_spec.rb
+++ b/plugins/chat/spec/models/direct_message_spec.rb
@@ -20,7 +20,8 @@ describe DirectMessage do
expect(direct_message.chat_channel_title_for_user(chat_channel, user1)).to eq(
I18n.t(
"chat.channel.dm_title.multi_user",
- users: [user3, user2].map { |u| "@#{u.username}" }.join(", "),
+ comma_separated_usernames:
+ [user3, user2].map { |u| "@#{u.username}" }.join(I18n.t("word_connector.comma")),
),
)
end
@@ -36,8 +37,12 @@ describe DirectMessage do
expect(direct_message.chat_channel_title_for_user(chat_channel, user1)).to eq(
I18n.t(
"chat.channel.dm_title.multi_user_truncated",
- users: users[1..5].sort_by(&:username).map { |u| "@#{u.username}" }.join(", "),
- leftover: 2,
+ comma_separated_usernames:
+ users[1..5]
+ .sort_by(&:username)
+ .map { |u| "@#{u.username}" }
+ .join(I18n.t("word_connector.comma")),
+ count: 2,
),
)
end
@@ -46,7 +51,7 @@ describe DirectMessage do
direct_message = Fabricate(:direct_message, users: [user1, user2])
expect(direct_message.chat_channel_title_for_user(chat_channel, user1)).to eq(
- I18n.t("chat.channel.dm_title.single_user", user: "@#{user2.username}"),
+ I18n.t("chat.channel.dm_title.single_user", username: "@#{user2.username}"),
)
end
@@ -54,7 +59,7 @@ describe DirectMessage do
direct_message = Fabricate(:direct_message, users: [user1])
expect(direct_message.chat_channel_title_for_user(chat_channel, user1)).to eq(
- I18n.t("chat.channel.dm_title.single_user", user: "@#{user1.username}"),
+ I18n.t("chat.channel.dm_title.single_user", username: "@#{user1.username}"),
)
end
diff --git a/plugins/chat/spec/requests/chat_controller_spec.rb b/plugins/chat/spec/requests/chat_controller_spec.rb
index 9f1729837d0..d0fcbfd19ab 100644
--- a/plugins/chat/spec/requests/chat_controller_spec.rb
+++ b/plugins/chat/spec/requests/chat_controller_spec.rb
@@ -320,7 +320,7 @@ RSpec.describe Chat::ChatController do
post "/chat/#{chat_channel.id}.json", params: { message: message }
expect(response.status).to eq(422)
expect(response.parsed_body["errors"]).to include(
- I18n.t("chat.errors.channel_new_message_disallowed", status: chat_channel.status_name),
+ I18n.t("chat.errors.channel_new_message_disallowed.closed"),
)
end
@@ -336,7 +336,7 @@ RSpec.describe Chat::ChatController do
post "/chat/#{chat_channel.id}.json", params: { message: message }
expect(response.status).to eq(422)
expect(response.parsed_body["errors"]).to include(
- I18n.t("chat.errors.channel_new_message_disallowed", status: chat_channel.status_name),
+ I18n.t("chat.errors.channel_new_message_disallowed.read_only"),
)
end
@@ -903,7 +903,7 @@ RSpec.describe Chat::ChatController do
}.not_to change { chat_message.reactions.where(user: user, emoji: emoji).count }
expect(response.status).to eq(403)
expect(response.parsed_body["errors"]).to include(
- I18n.t("chat.errors.channel_modify_message_disallowed", status: chat_channel.status_name),
+ I18n.t("chat.errors.channel_modify_message_disallowed.#{chat_channel.status}"),
)
end
diff --git a/plugins/chat/spec/requests/incoming_chat_webhooks_controller_spec.rb b/plugins/chat/spec/requests/incoming_chat_webhooks_controller_spec.rb
index a8a54334718..6c049a1f050 100644
--- a/plugins/chat/spec/requests/incoming_chat_webhooks_controller_spec.rb
+++ b/plugins/chat/spec/requests/incoming_chat_webhooks_controller_spec.rb
@@ -55,7 +55,7 @@ RSpec.describe Chat::IncomingChatWebhooksController do
}.not_to change { ChatMessage.where(chat_channel: chat_channel).count }
expect(response.status).to eq(422)
expect(response.parsed_body["errors"]).to include(
- I18n.t("chat.errors.channel_new_message_disallowed", status: chat_channel.status_name),
+ I18n.t("chat.errors.channel_new_message_disallowed.read_only"),
)
end
diff --git a/plugins/chat/spec/system/closed_channel_spec.rb b/plugins/chat/spec/system/closed_channel_spec.rb
index 7237db225fe..5c19e7564c6 100644
--- a/plugins/chat/spec/system/closed_channel_spec.rb
+++ b/plugins/chat/spec/system/closed_channel_spec.rb
@@ -30,11 +30,7 @@ RSpec.describe "Closed channel", type: :system, js: true do
chat.visit_channel(channel_1)
expect(page).to have_field(
- placeholder:
- I18n.t(
- "js.chat.placeholder_new_message_disallowed",
- status: I18n.t("js.chat.channel_status.closed").downcase,
- ),
+ placeholder: I18n.t("js.chat.placeholder_new_message_disallowed.closed"),
disabled: true,
)
end
@@ -54,7 +50,7 @@ RSpec.describe "Closed channel", type: :system, js: true do
chat.visit_channel(channel_1)
expect(page).to have_no_field(
- placeholder: I18n.t("js.chat.placeholder_new_message_disallowed"),
+ placeholder: I18n.t("js.chat.placeholder_new_message_disallowed.closed"),
disabled: true,
)
end
diff --git a/plugins/chat/spec/system/create_channel_spec.rb b/plugins/chat/spec/system/create_channel_spec.rb
index 294683dec1c..27a0de52dc5 100644
--- a/plugins/chat/spec/system/create_channel_spec.rb
+++ b/plugins/chat/spec/system/create_channel_spec.rb
@@ -69,7 +69,7 @@ RSpec.describe "Create channel", type: :system, js: true do
end
end
- context "when category has a malicous group name" do
+ context "when category has a malicious group name" do
fab!(:group_1) do
group = Group.new(name: "")
group.save(validate: false)
diff --git a/plugins/chat/spec/system/jit_messages_spec.rb b/plugins/chat/spec/system/jit_messages_spec.rb
index d5e0a2e7df4..0f0628b1ac9 100644
--- a/plugins/chat/spec/system/jit_messages_spec.rb
+++ b/plugins/chat/spec/system/jit_messages_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe "JIT messages", type: :system, js: true do
channel.send_message("hi @#{other_user.username}")
expect(page).to have_content(
- I18n.t("js.chat.mention_warning.without_membership.one", username: other_user.username),
+ I18n.t("js.chat.mention_warning.without_membership", username: other_user.username),
wait: 5,
)
end
@@ -44,7 +44,7 @@ RSpec.describe "JIT messages", type: :system, js: true do
channel.send_message("hi @#{other_user.username}")
expect(page).to have_content(
- I18n.t("js.chat.mention_warning.cannot_see.one", username: other_user.username),
+ I18n.t("js.chat.mention_warning.cannot_see", username: other_user.username),
wait: 5,
)
end
@@ -61,7 +61,7 @@ RSpec.describe "JIT messages", type: :system, js: true do
channel.send_message("hi @#{group_1.name}")
expect(page).to have_content(
- I18n.t("js.chat.mention_warning.group_mentions_disabled.one", group_name: group_1.name),
+ I18n.t("js.chat.mention_warning.group_mentions_disabled", group_name: group_1.name),
wait: 5,
)
end
diff --git a/plugins/chat/spec/system/read_only_spec.rb b/plugins/chat/spec/system/read_only_spec.rb
index 3610e55020e..ffadc0dce03 100644
--- a/plugins/chat/spec/system/read_only_spec.rb
+++ b/plugins/chat/spec/system/read_only_spec.rb
@@ -30,7 +30,7 @@ RSpec.describe "Read only", type: :system, js: true do
chat.visit_channel(channel_1)
expect(page).to have_field(
- placeholder: I18n.t("js.chat.placeholder_new_message_disallowed", status: "read only"),
+ placeholder: I18n.t("js.chat.placeholder_new_message_disallowed.read_only"),
disabled: true,
)
end
@@ -50,7 +50,7 @@ RSpec.describe "Read only", type: :system, js: true do
chat.visit_channel(channel_1)
expect(page).to have_field(
- placeholder: I18n.t("js.chat.placeholder_new_message_disallowed", status: "read only"),
+ placeholder: I18n.t("js.chat.placeholder_new_message_disallowed.read_only"),
disabled: true,
)
end
diff --git a/script/i18n_lint.rb b/script/i18n_lint.rb
index f3f96abf87d..794b07b34ae 100755
--- a/script/i18n_lint.rb
+++ b/script/i18n_lint.rb
@@ -37,8 +37,6 @@ class LocaleFileValidator
"Pluralized strings must have only the sub-keys 'one' and 'other'.\nThe following keys have missing or additional keys:",
invalid_one_keys:
"The following keys contain the number 1 instead of the interpolation key %{count}:",
- invalid_message_format_one_key:
- "The following keys use 'one {1 foo}' instead of the generic 'one {# foo}':",
}
PLURALIZATION_KEYS = %w[zero one two few many other]
@@ -88,7 +86,6 @@ class LocaleFileValidator
@errors[:invalid_relative_links] = []
@errors[:invalid_relative_image_sources] = []
@errors[:invalid_interpolation_key_format] = []
- @errors[:invalid_message_format_one_key] = []
each_translation(yaml) do |key, value|
@errors[:invalid_relative_links] << key if value.match?(%r{href\s*=\s*["']/[^/]|\]\(/[^/]}i)
@@ -98,10 +95,6 @@ class LocaleFileValidator
if value.match?(/{{.+?}}/) && !key.end_with?("_MF")
@errors[:invalid_interpolation_key_format] << key
end
-
- if key.end_with?("_MF") && value.match?(/one {.*?1.*?}/)
- @errors[:invalid_message_format_one_key] << key
- end
end
end
diff --git a/spec/models/translation_override_spec.rb b/spec/models/translation_override_spec.rb
index 20f3200b430..d8c8a5c3971 100644
--- a/spec/models/translation_override_spec.rb
+++ b/spec/models/translation_override_spec.rb
@@ -27,6 +27,7 @@ RSpec.describe TranslationOverride do
I18n.t(
"activerecord.errors.models.translation_overrides.attributes.value.invalid_interpolation_keys",
keys: "key, omg",
+ count: 2,
),
)
end
@@ -61,6 +62,7 @@ RSpec.describe TranslationOverride do
I18n.t(
"activerecord.errors.models.translation_overrides.attributes.value.invalid_interpolation_keys",
keys: "something",
+ count: 1,
),
)
end
@@ -78,6 +80,7 @@ RSpec.describe TranslationOverride do
I18n.t(
"activerecord.errors.models.translation_overrides.attributes.value.invalid_interpolation_keys",
keys: "topic_title_url_encoded",
+ count: 1,
),
)
end
@@ -132,6 +135,7 @@ RSpec.describe TranslationOverride do
I18n.t(
"activerecord.errors.models.translation_overrides.attributes.value.invalid_interpolation_keys",
keys: "key3, key4",
+ count: 2,
),
)
end
diff --git a/spec/requests/admin/email_templates_controller_spec.rb b/spec/requests/admin/email_templates_controller_spec.rb
index e9e15341bfb..4fb80b48daf 100644
--- a/spec/requests/admin/email_templates_controller_spec.rb
+++ b/spec/requests/admin/email_templates_controller_spec.rb
@@ -165,6 +165,7 @@ RSpec.describe Admin::EmailTemplatesController do
I18n.t(
"activerecord.errors.models.translation_overrides.attributes.value.invalid_interpolation_keys",
keys: "email_wrongfix",
+ count: 1,
)
}",
]
@@ -183,6 +184,7 @@ RSpec.describe Admin::EmailTemplatesController do
I18n.t(
"activerecord.errors.models.translation_overrides.attributes.value.invalid_interpolation_keys",
keys: "invalid",
+ count: 1,
)
}",
]
@@ -201,12 +203,14 @@ RSpec.describe Admin::EmailTemplatesController do
I18n.t(
"activerecord.errors.models.translation_overrides.attributes.value.invalid_interpolation_keys",
keys: "invalid",
+ count: 1,
)
}",
"Body: #{
I18n.t(
"activerecord.errors.models.translation_overrides.attributes.value.invalid_interpolation_keys",
keys: "invalid",
+ count: 1,
)
}",
]
diff --git a/spec/requests/admin/site_texts_controller_spec.rb b/spec/requests/admin/site_texts_controller_spec.rb
index 0bdace38ede..14b3f2455c3 100644
--- a/spec/requests/admin/site_texts_controller_spec.rb
+++ b/spec/requests/admin/site_texts_controller_spec.rb
@@ -580,6 +580,7 @@ RSpec.describe Admin::SiteTextsController do
I18n.t(
"activerecord.errors.models.translation_overrides.attributes.value.invalid_interpolation_keys",
keys: "key, omg",
+ count: 2,
),
)
end