diff --git a/app/assets/javascripts/admin/templates/modal/admin_badge_preview.hbs b/app/assets/javascripts/admin/templates/modal/admin_badge_preview.hbs
index 835a105cd..e244d5b0e 100644
--- a/app/assets/javascripts/admin/templates/modal/admin_badge_preview.hbs
+++ b/app/assets/javascripts/admin/templates/modal/admin_badge_preview.hbs
@@ -14,7 +14,13 @@
     </ul>
     -->
   {{else}}
-    <p class="grant-count">{{{i18n 'admin.badges.preview.grant_count' count=count}}}</p>
+    <p class="grant-count">
+      {{#if count}}
+        {{{i18n 'admin.badges.preview.grant_count' count=count}}}
+      {{else}}
+        {{{i18n 'admin.badges.preview.no_grant_count'}}}
+      {{/if}}
+    </p>
 
     {{#if count_warning}}
       <div class="count-warning">
diff --git a/app/assets/javascripts/discourse/components/post-menu.js.es6 b/app/assets/javascripts/discourse/components/post-menu.js.es6
index 765539245..2b3e28e72 100644
--- a/app/assets/javascripts/discourse/components/post-menu.js.es6
+++ b/app/assets/javascripts/discourse/components/post-menu.js.es6
@@ -248,7 +248,9 @@ const PostMenuComponent = Ember.Component.extend(StringBuffer, {
     if (likeCount > 0) {
       const likedPost = !!this.get('post.likeAction.acted');
 
-      const label = likedPost ? 'post.has_likes_title_you' : 'post.has_likes_title';
+      const label = likedPost
+        ? likeCount === 1 ? 'post.has_likes_title_only_you' : 'post.has_likes_title_you'
+        : 'post.has_likes_title';
 
       return new Button('like-count', label, undefined, {
         className: 'like-count highlight-action',
diff --git a/app/assets/javascripts/discourse/controllers/feature-topic.js.es6 b/app/assets/javascripts/discourse/controllers/feature-topic.js.es6
index 4b189d168..34c1c9516 100644
--- a/app/assets/javascripts/discourse/controllers/feature-topic.js.es6
+++ b/app/assets/javascripts/discourse/controllers/feature-topic.js.es6
@@ -41,7 +41,8 @@ export default Ember.Controller.extend(ModalFunctionality, {
 
   @computed("categoryLink", "pinnedInCategoryCount")
   alreadyPinnedMessage(categoryLink, count) {
-    return I18n.t("topic.feature_topic.already_pinned", { categoryLink, count });
+    const key = count === 0 ? "topic.feature_topic.not_pinned" : "topic.feature_topic.already_pinned";
+    return I18n.t(key, { categoryLink, count });
   },
 
   @computed("parsedPinnedInCategoryUntil")
diff --git a/app/assets/javascripts/discourse/models/nav-item.js.es6 b/app/assets/javascripts/discourse/models/nav-item.js.es6
index 64cb9fea4..1d614c0d1 100644
--- a/app/assets/javascripts/discourse/models/nav-item.js.es6
+++ b/app/assets/javascripts/discourse/models/nav-item.js.es6
@@ -12,12 +12,13 @@ const NavItem = Discourse.Model.extend({
     }
 
     var extra = { count: count };
+    var titleKey = count === 0 ? '.title' : '.title_with_count';
 
     if (categoryName) {
       name = 'category';
       extra.categoryName = toTitleCase(categoryName);
     }
-    return I18n.t("filters." + name.replace("/", ".") + ".title", extra);
+    return I18n.t("filters." + name.replace("/", ".") + titleKey, extra);
   }.property('categoryName', 'name', 'count'),
 
   categoryName: function() {
diff --git a/app/assets/javascripts/discourse/routes/build-category-route.js.es6 b/app/assets/javascripts/discourse/routes/build-category-route.js.es6
index 8456eaf4f..219ae7d32 100644
--- a/app/assets/javascripts/discourse/routes/build-category-route.js.es6
+++ b/app/assets/javascripts/discourse/routes/build-category-route.js.es6
@@ -57,7 +57,7 @@ export default (filter, params) => {
     },
 
     titleToken() {
-      const filterText = I18n.t('filters.' + filter.replace('/', '.') + '.title', { count: 0 }),
+      const filterText = I18n.t('filters.' + filter.replace('/', '.') + '.title'),
             category = this.currentModel.category;
 
       return I18n.t('filters.with_category', { filter: filterText, category: category.get('name') });
diff --git a/app/assets/javascripts/discourse/routes/build-topic-route.js.es6 b/app/assets/javascripts/discourse/routes/build-topic-route.js.es6
index 0da680a20..890f0729f 100644
--- a/app/assets/javascripts/discourse/routes/build-topic-route.js.es6
+++ b/app/assets/javascripts/discourse/routes/build-topic-route.js.es6
@@ -80,7 +80,7 @@ export default function(filter, extras) {
     titleToken() {
       if (filter === Discourse.Utilities.defaultHomepage()) { return; }
 
-      const filterText = I18n.t('filters.' + filter.replace('/', '.') + '.title', {count: 0});
+      const filterText = I18n.t('filters.' + filter.replace('/', '.') + '.title');
       return I18n.t('filters.with_topics', {filter: filterText});
     },
 
diff --git a/app/assets/javascripts/discourse/templates/components/hamburger-menu.hbs b/app/assets/javascripts/discourse/templates/components/hamburger-menu.hbs
index 3d875eb60..6c3640a6c 100644
--- a/app/assets/javascripts/discourse/templates/components/hamburger-menu.hbs
+++ b/app/assets/javascripts/discourse/templates/components/hamburger-menu.hbs
@@ -41,14 +41,22 @@
   {{/if}}
 
   {{#menu-links}}
-    <li>{{d-link route="discovery.latest" class="latest-topics-link" label="filters.latest.title.zero"}}</li>
+    <li>{{d-link route="discovery.latest" class="latest-topics-link" label="filters.latest.title"}}</li>
 
     {{#if currentUser}}
       <li>
-        {{d-link route="discovery.new" class="new-topics-link" label="filters.new.title" count=newCount}}
+        {{#if newCount}}
+          {{d-link route="discovery.new" class="new-topics-link" label="filters.new.title_with_count" count=newCount}}
+        {{else}}
+          {{d-link route="discovery.new" class="new-topics-link" label="filters.new.title"}}
+        {{/if}}
       </li>
       <li>
-        {{d-link route="discovery.unread" class="unread-topics-link" label="filters.unread.title" count=unreadCount}}
+        {{#if unreadCount}}
+          {{d-link route="discovery.unread" class="unread-topics-link" label="filters.unread.title_with_count" count=unreadCount}}
+        {{else}}
+          {{d-link route="discovery.unread" class="unread-topics-link" label="filters.unread.title"}}
+        {{/if}}
       </li>
     {{/if}}
     <li>{{d-link route="discovery.top" class="top-topics-link" label="filters.top.title"}}</li>
diff --git a/app/assets/javascripts/discourse/templates/modal/feature-topic.hbs b/app/assets/javascripts/discourse/templates/modal/feature-topic.hbs
index 7aee95425..942fa2611 100644
--- a/app/assets/javascripts/discourse/templates/modal/feature-topic.hbs
+++ b/app/assets/javascripts/discourse/templates/modal/feature-topic.hbs
@@ -5,7 +5,11 @@
         {{#if model.pinned_globally}}
           <p>
             {{#conditional-loading-spinner size="small" condition=loading}}
-              {{{i18n "topic.feature_topic.already_pinned_globally" count=pinnedGloballyCount}}}
+              {{#if pinnedGloballyCount}}
+                {{{i18n "topic.feature_topic.already_pinned_globally" count=pinnedGloballyCount}}}
+              {{else}}
+                {{{i18n "topic.feature_topic.not_pinned_globally"}}}
+              {{/if}}
             {{/conditional-loading-spinner}}
           </p>
           <p>{{i18n "topic.feature_topic.global_pin_note"}}</p>
@@ -48,7 +52,11 @@
       <div class="desc">
         <p>
           {{#conditional-loading-spinner size="small" condition=loading}}
-            {{{i18n "topic.feature_topic.already_pinned_globally" count=pinnedGloballyCount}}}
+            {{#if pinnedGloballyCount}}
+              {{{i18n "topic.feature_topic.already_pinned_globally" count=pinnedGloballyCount}}}
+            {{else}}
+              {{{i18n "topic.feature_topic.not_pinned_globally"}}}
+            {{/if}}
           {{/conditional-loading-spinner}}
         </p>
         <p>
@@ -71,7 +79,11 @@
     <div class="desc">
       <p>
         {{#conditional-loading-spinner size="small" condition=loading}}
-          {{{i18n "topic.feature_topic.already_banner" count=bannerCount}}}
+          {{#if bannerCount}}
+            {{{i18n "topic.feature_topic.banner_exists"}}}
+          {{else}}
+            {{{i18n "topic.feature_topic.no_banner_exists"}}}
+          {{/if}}
         {{/conditional-loading-spinner}}
       </p>
       <p>
diff --git a/app/assets/javascripts/discourse/templates/user/preferences.hbs b/app/assets/javascripts/discourse/templates/user/preferences.hbs
index d5841c1b9..643757fc7 100644
--- a/app/assets/javascripts/discourse/templates/user/preferences.hbs
+++ b/app/assets/javascripts/discourse/templates/user/preferences.hbs
@@ -182,7 +182,11 @@
       {{preference-checkbox labelKey="user.email_always" checked=model.email_always}}
 
       <div class='instructions'>
-        {{i18n 'user.email.frequency' count=siteSettings.email_time_window_mins}}
+        {{#if siteSettings.email_time_window_mins}}
+          {{i18n 'user.email.frequency' count=siteSettings.email_time_window_mins}}
+        {{else}}
+          {{i18n 'user.email.frequency_immediately'}}
+        {{/if}}
       </div>
     </div>
 
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 62a7baae0..72c88369c 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -538,8 +538,8 @@ en:
         ok: "We will email you to confirm"
         invalid: "Please enter a valid email address"
         authenticated: "Your email has been authenticated by {{provider}}"
+        frequency_immediately: "We'll email you immediately if you haven't read the thing we're emailing you about."
         frequency:
-          zero: "We'll email you immediately if you haven't read the thing we're emailing you about."
           one: "We'll only email you if we haven't seen you in the last minute."
           other: "We'll only email you if we haven't seen you in the last {{count}} minutes."
 
@@ -1231,25 +1231,24 @@ en:
         unpin_until: "Remove this topic from the top of the {{categoryLink}} category or wait until <strong>%{until}</strong>."
         pin_note: "Users can unpin the topic individually for themselves."
         pin_validation: "A date is required to pin this topic."
+        not_pinned: "There are no topics pinned in {{categoryLink}}."
         already_pinned:
-          zero: "There are no topics pinned in {{categoryLink}}."
-          one: "Topics currently pinned in {{categoryLink}}: <strong class='badge badge-notification unread'>1</strong>."
-          other: "Topics currently pinned in {{categoryLink}}: <strong class='badge badge-notification unread'>{{count}}</strong>."
+          one: "Topics currently pinned in {{categoryLink}}: <strong class='badge badge-notification unread'>1</strong>"
+          other: "Topics currently pinned in {{categoryLink}}: <strong class='badge badge-notification unread'>{{count}}</strong>"
         pin_globally: "Make this topic appear at the top of all topic lists until"
         confirm_pin_globally: "You already have {{count}} globally pinned topics. Too many pinned topics may be a burden for new and anonymous users. Are you sure you want to pin another topic globally?"
         unpin_globally: "Remove this topic from the top of all topic lists."
         unpin_globally_until: "Remove this topic from the top of all topic lists or wait until <strong>%{until}</strong>."
         global_pin_note: "Users can unpin the topic individually for themselves."
+        not_pinned_globally: "There are no topics pinned globally."
         already_pinned_globally:
-          zero: "There are no topics pinned globally."
-          one: "Topics currently pinned globally: <strong class='badge badge-notification unread'>1</strong>."
-          other: "Topics currently pinned globally: <strong class='badge badge-notification unread'>{{count}}</strong>."
+          one: "Topics currently pinned globally: <strong class='badge badge-notification unread'>1</strong>"
+          other: "Topics currently pinned globally: <strong class='badge badge-notification unread'>{{count}}</strong>"
         make_banner: "Make this topic into a banner that appears at the top of all pages."
         remove_banner: "Remove the banner that appears at the top of all pages."
         banner_note: "Users can dismiss the banner by closing it. Only one topic can be bannered at any given time."
-        already_banner:
-          zero: "There is no banner topic."
-          one: "There <strong class='badge badge-notification unread'>is</strong> currently a banner topic."
+        no_banner_exists: "There is no banner topic."
+        banner_exists: "There <strong class='badge badge-notification unread'>is</strong> currently a banner topic."
 
       inviting: "Inviting..."
       automatically_add_to_groups_optional: "This invite also includes access to these groups: (optional, admin only)"
@@ -1370,8 +1369,8 @@ en:
         one: "1 person liked this post"
         other: "{{count}} people liked this post"
 
+      has_likes_title_only_you: "you liked this post"
       has_likes_title_you:
-        zero: "you liked this post"
         one: "you and 1 other person liked this post"
         other: "you and {{count}} other people liked this post"
 
@@ -1521,11 +1520,6 @@ en:
             one: "1 person voted for this post"
             other: "{{count}} people voted for this post"
 
-      edits:
-        one: 1 edit
-        other: "{{count}} edits"
-        zero: no edits
-
       delete:
         confirm:
           one: "Are you sure you want to delete that post?"
@@ -1606,8 +1600,6 @@ en:
       position_disabled_click: 'enable the "fixed category positions" setting.'
       parent: "Parent Category"
       notifications:
-        title: ''
-        reasons:
         watching:
           title: "Watching"
           description: "You will automatically watch all new topics in these categories. You will be notified of every new post in every topic, and a count of new replies will be shown."
@@ -1723,8 +1715,8 @@ en:
       with_topics: "%{filter} topics"
       with_category: "%{filter} %{category} topics"
       latest:
-        title:
-          zero: "Latest"
+        title: "Latest"
+        title_with_count:
           one: "Latest (1)"
           other: "Latest ({{count}})"
         help: "topics with recent posts"
@@ -1742,23 +1734,21 @@ en:
         title_in: "Category - {{categoryName}}"
         help: "all topics grouped by category"
       unread:
-        title:
-          zero: "Unread"
+        title: "Unread"
+        title_with_count:
           one: "Unread (1)"
           other: "Unread ({{count}})"
         help: "topics you are currently watching or tracking with unread posts"
         lower_title_with_count:
-          zero: ""
           one: "1 unread"
           other: "{{count}} unread"
       new:
         lower_title_with_count:
-          zero: ""
           one: "1 new"
           other: "{{count}} new"
         lower_title: "new"
-        title:
-          zero: "New"
+        title: "New"
+        title_with_count:
           one: "New (1)"
           other: "New ({{count}})"
         help: "topics created in the last few days"
@@ -1769,8 +1759,8 @@ en:
         title: "Bookmarks"
         help: "topics you have bookmarked"
       category:
-        title:
-          zero: "{{categoryName}}"
+        title: "{{categoryName}}"
+        title_with_count:
           one: "{{categoryName}} (1)"
           other: "{{categoryName}} ({{count}})"
         help: "latest topics in the {{categoryName}} category"
@@ -2572,8 +2562,8 @@ en:
           bad_count_warning:
             header: "WARNING!"
             text: "There are missing grant samples. This happens when the badge query returns user IDs or post IDs that do not exist. This may cause unexpected results later on - please double-check your query."
+          no_grant_count: "No badges to be assigned."
           grant_count:
-            zero: "No badges to be assigned."
             one: "<b>1</b> badge to be assigned."
             other: "<b>%{count}</b> badges to be assigned."
           sample: "Sample:"
diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index 1415c098b..a6e3d0d9f 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -140,26 +140,27 @@ en:
       one: "1 reply"
       other: "%{count} replies"
 
+  no_mentions_allowed: "Sorry, you can't mention other users."
   too_many_mentions:
-    zero: "Sorry, you can't mention other users."
     one: "Sorry, you can only mention one other user in a post."
     other: "Sorry, you can only mention %{count} users in a post."
+  no_mentions_allowed_newuser: "Sorry, new users can't mention other users."
   too_many_mentions_newuser:
-    zero: "Sorry, new users can't mention other users."
     one: "Sorry, new users can only mention one other user in a post."
     other: "Sorry, new users can only mention %{count} users in a post."
+  no_images_allowed: "Sorry, new users can't put images in posts."
   too_many_images:
-    zero: "Sorry, new users can't put images in posts."
     one: "Sorry, new users can only put one image in a post."
     other: "Sorry, new users can only put %{count} images in a post."
+  no_attachments_allowed: "Sorry, new users can't put attachments in posts."
   too_many_attachments:
-    zero: "Sorry, new users can't put attachments in posts."
     one: "Sorry, new users can only put one attachment in a post."
     other: "Sorry, new users can only put %{count} attachments in a post."
+  no_links_allowed: "Sorry, new users can't put links in posts."
   too_many_links:
-    zero: "Sorry, new users can't put links in posts."
     one: "Sorry, new users can only put one link in a post."
     other: "Sorry, new users can only put %{count} links in a post."
+
   spamming_host: "Sorry you cannot post a link to that host."
   user_is_suspended: "Suspended users are not allowed to post."
   topic_not_found: "Something has gone wrong. Perhaps this topic was closed or deleted while you were looking at it?"
diff --git a/lib/validators/post_validator.rb b/lib/validators/post_validator.rb
index fc1657147..29dcb9a9e 100644
--- a/lib/validators/post_validator.rb
+++ b/lib/validators/post_validator.rb
@@ -51,9 +51,9 @@ class Validators::PostValidator < ActiveModel::Validator
   # Ensure maximum amount of mentions in a post
   def max_mention_validator(post)
     if acting_user_is_trusted?(post)
-      add_error_if_count_exceeded(post, :too_many_mentions, post.raw_mentions.size, SiteSetting.max_mentions_per_post)
+      add_error_if_count_exceeded(post, :no_mentions_allowed, :too_many_mentions, post.raw_mentions.size, SiteSetting.max_mentions_per_post)
     else
-      add_error_if_count_exceeded(post, :too_many_mentions_newuser, post.raw_mentions.size, SiteSetting.newuser_max_mentions_per_post)
+      add_error_if_count_exceeded(post, :no_mentions_allowed_newuser, :too_many_mentions_newuser, post.raw_mentions.size, SiteSetting.newuser_max_mentions_per_post)
     end
   end
 
@@ -65,17 +65,17 @@ class Validators::PostValidator < ActiveModel::Validator
 
   # Ensure new users can not put too many images in a post
   def max_images_validator(post)
-    add_error_if_count_exceeded(post, :too_many_images, post.image_count, SiteSetting.newuser_max_images) unless acting_user_is_trusted?(post)
+    add_error_if_count_exceeded(post, :no_images_allowed, :too_many_images, post.image_count, SiteSetting.newuser_max_images) unless acting_user_is_trusted?(post)
   end
 
   # Ensure new users can not put too many attachments in a post
   def max_attachments_validator(post)
-    add_error_if_count_exceeded(post, :too_many_attachments, post.attachment_count, SiteSetting.newuser_max_attachments) unless acting_user_is_trusted?(post)
+    add_error_if_count_exceeded(post, :no_attachments_allowed, :too_many_attachments, post.attachment_count, SiteSetting.newuser_max_attachments) unless acting_user_is_trusted?(post)
   end
 
   # Ensure new users can not put too many links in a post
   def max_links_validator(post)
-    add_error_if_count_exceeded(post, :too_many_links, post.link_count, SiteSetting.newuser_max_links) unless acting_user_is_trusted?(post)
+    add_error_if_count_exceeded(post, :no_links_allowed, :too_many_links, post.link_count, SiteSetting.newuser_max_links) unless acting_user_is_trusted?(post)
   end
 
   # Stop us from posting the same thing too quickly
@@ -98,7 +98,13 @@ class Validators::PostValidator < ActiveModel::Validator
     post.acting_user.present? && post.acting_user.has_trust_level?(TrustLevel[1])
   end
 
-  def add_error_if_count_exceeded(post, key_for_translation, current_count, max_count)
-    post.errors.add(:base, I18n.t(key_for_translation, count: max_count)) if current_count > max_count
+  def add_error_if_count_exceeded(post, not_allowed_translation_key, limit_translation_key, current_count, max_count)
+    if current_count > max_count
+      if max_count == 0
+        post.errors.add(:base, I18n.t(not_allowed_translation_key))
+      else
+        post.errors.add(:base, I18n.t(limit_translation_key, count: max_count))
+      end
+    end
   end
 end
diff --git a/spec/integrity/i18n_spec.rb b/spec/integrity/i18n_spec.rb
index e7b9c08fe..5e95b706a 100644
--- a/spec/integrity/i18n_spec.rb
+++ b/spec/integrity/i18n_spec.rb
@@ -58,7 +58,7 @@ describe "i18n integrity checks" do
     end
   end
 
-  describe 'keys in English locale files' do
+  describe 'English locale file' do
     locale_files = ['config/locales', 'plugins/**/locales']
                      .product(['server.en.yml', 'client.en.yml'])
                      .collect { |dir, filename| Dir["#{Rails.root}/#{dir}/#{filename}"] }
@@ -85,12 +85,42 @@ describe "i18n integrity checks" do
       end
     end
 
+    module Pluralizations
+      def self.load(path)
+        whitelist = Regexp.union([/messages.restrict_dependent_destroy/])
+
+        yaml = YAML.load_file("#{Rails.root}/#{path}")
+        pluralizations = find_pluralizations(yaml['en'])
+        pluralizations.reject! { |key| key.match(whitelist) }
+        pluralizations
+      end
+
+      def self.find_pluralizations(hash, parent_key = '', pluralizations = Hash.new)
+        hash.each do |key, value|
+          if value.is_a? Hash
+            current_key = parent_key.blank? ? key : "#{parent_key}.#{key}"
+            find_pluralizations(value, current_key, pluralizations)
+          elsif key == 'one' || key == 'other'
+            pluralizations[parent_key] = hash
+          end
+        end
+
+        pluralizations
+      end
+    end
+
     locale_files.each do |path|
       context path do
         it 'has no duplicate keys' do
           duplicates = DuplicateKeyFinder.new.find_duplicates("#{Rails.root}/#{path}")
           expect(duplicates).to be_empty
         end
+
+        Pluralizations.load(path).each do |key, values|
+          it "key '#{key}' has valid pluralizations" do
+            expect(values.keys).to contain_exactly('one', 'other')
+          end
+        end
       end
     end
   end