FEATURE: global admin override of most of the user preferences

This commit is contained in:
Régis Hanol 2015-08-21 20:39:21 +02:00
parent 73264648f2
commit bef80633b1
56 changed files with 438 additions and 215 deletions

View File

@ -4,7 +4,7 @@ import SiteSetting from 'admin/models/site-setting';
import { propertyNotEqual } from 'discourse/lib/computed';
import computed from 'ember-addons/ember-computed-decorators';
const CustomTypes = ['bool', 'enum', 'list', 'url_list', 'host_list'];
const CustomTypes = ['bool', 'enum', 'list', 'url_list', 'host_list', 'category_list'];
export default Ember.Component.extend(BufferedContent, ScrollTop, {
classNameBindings: [':row', ':setting', 'setting.overridden', 'typeClass'],
@ -12,44 +12,32 @@ export default Ember.Component.extend(BufferedContent, ScrollTop, {
dirty: propertyNotEqual('buffered.value', 'setting.value'),
validationMessage: null,
preview: function() {
const preview = this.get('setting.preview');
@computed("setting.preview", "buffered.value")
preview(preview, value) {
if (preview) {
return new Handlebars.SafeString("<div class='preview'>" +
preview.replace(/\{\{value\}\}/g, this.get('buffered.value')) +
"</div>");
}
}.property('buffered.value'),
@computed('partialType')
typeClass() {
return this.get('partialType').replace("_", "-");
},
@computed('buffered.value')
enabled: {
get(bufferedValue) {
if (Ember.isEmpty(bufferedValue)) { return false; }
return bufferedValue === 'true';
},
set(value) {
this.set('buffered.value', value ? 'true' : 'false');
return value;
return new Handlebars.SafeString("<div class='preview'>" + preview.replace(/\{\{value\}\}/g, value) + "</div>");
}
},
settingName: function() {
return this.get('setting.setting').replace(/\_/g, ' ');
}.property('setting.setting'),
@computed('componentType')
typeClass(componentType) {
return componentType.replace("_", "-");
},
partialType: function() {
let type = this.get('setting.type');
@computed("setting.setting")
settingName(setting) {
return setting.replace(/\_/g, ' ');
},
@computed("setting.type")
componentType(type) {
return CustomTypes.indexOf(type) !== -1 ? type : 'string';
}.property('setting.type'),
},
partialName: function() {
return 'admin/templates/site-settings/' + this.get('partialType');
}.property('partialType'),
@computed("typeClass")
componentName(typeClass) {
return "site-settings/" + typeClass;
},
_watchEnterKey: function() {
const self = this;
@ -65,8 +53,8 @@ export default Ember.Component.extend(BufferedContent, ScrollTop, {
}.on("willDestroyElement"),
_save() {
const setting = this.get('buffered');
const self = this;
const self = this,
setting = this.get('buffered');
SiteSetting.update(setting.get('setting'), setting.get('value')).then(function() {
self.set('validationMessage', null);
self.commitBuffer();

View File

@ -0,0 +1,17 @@
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({
@computed("value")
enabled: {
get(value) {
if (Ember.isEmpty(value)) { return false; }
return value === "true";
},
set(value) {
this.set("value", value ? "true" : "false");
return value;
}
},
});

View File

@ -0,0 +1,16 @@
import computed from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({
@computed("value")
selectedCategories: {
get(value) {
return Discourse.Category.findByIds(value.split("|"));
},
set(value) {
this.set("value", value.mapBy("id").join("|"));
return value;
}
}
});

View File

@ -2,7 +2,7 @@
<h3>{{unbound settingName}}</h3>
</div>
<div class="setting-value">
{{partial partialName}}
{{component componentName setting=setting value=buffered.value validationMessage=validationMessage}}
</div>
{{#if dirty}}
<div class='setting-controls'>

View File

@ -0,0 +1,3 @@
{{category-group categories=selectedCategories blacklist=selectedCategories}}
<div class='desc'>{{{unbound setting.description}}}</div>
{{setting-validation-message message=validationMessage}}

View File

@ -1,4 +1,4 @@
{{combo-box valueAttribute="value" content=setting.validValues value=buffered.value none=setting.allowsNone}}
{{combo-box valueAttribute="value" content=setting.validValues value=value none=setting.allowsNone}}
{{preview}}
{{setting-validation-message message=validationMessage}}
<div class='desc'>{{{unbound setting.description}}}</div>

View File

@ -1,3 +1,3 @@
{{value-list values=buffered.value addKey="admin.site_settings.add_url"}}
{{value-list values=value addKey="admin.site_settings.add_host"}}
{{setting-validation-message message=validationMessage}}
<div class='desc'>{{{unbound setting.description}}}</div>

View File

@ -1,3 +1,3 @@
{{list-setting settingValue=buffered.value choices=setting.choices settingName=setting.setting}}
{{list-setting settingValue=value choices=setting.choices settingName=setting.setting}}
{{setting-validation-message message=validationMessage}}
<div class='desc'>{{{unbound setting.description}}}</div>

View File

@ -1,3 +1,3 @@
{{text-field value=buffered.value classNames="input-setting-string"}}
{{text-field value=value classNames="input-setting-string"}}
{{setting-validation-message message=validationMessage}}
<div class='desc'>{{{unbound setting.description}}}</div>

View File

@ -1,3 +1,3 @@
{{value-list values=buffered.value addKey="admin.site_settings.add_host"}}
{{value-list values=value addKey="admin.site_settings.add_url"}}
{{setting-validation-message message=validationMessage}}
<div class='desc'>{{{unbound setting.description}}}</div>

View File

@ -24,13 +24,13 @@ export default Ember.Component.extend({
const slug = link.match(regexp)[1];
return Discourse.Category.findSingleBySlug(slug);
});
self.set("categories", categories);
Em.run.next(() => self.set("categories", categories));
},
template,
transformComplete(category) {
return categoryBadgeHTML(category, {allowUncategorized: true});
}
});
}.on('didInsertElement')
}.on('didInsertElement'),
});

View File

@ -71,19 +71,19 @@ export default Ember.Controller.extend(CanCheckEmails, {
autoTrackDurations: [{ name: I18n.t('user.auto_track_options.never'), value: -1 },
{ name: I18n.t('user.auto_track_options.immediately'), value: 0 },
{ name: I18n.t('user.auto_track_options.after_n_seconds', { count: 30 }), value: 30000 },
{ name: I18n.t('user.auto_track_options.after_n_minutes', { count: 1 }), value: 60000 },
{ name: I18n.t('user.auto_track_options.after_n_minutes', { count: 2 }), value: 120000 },
{ name: I18n.t('user.auto_track_options.after_n_minutes', { count: 3 }), value: 180000 },
{ name: I18n.t('user.auto_track_options.after_n_minutes', { count: 4 }), value: 240000 },
{ name: I18n.t('user.auto_track_options.after_n_minutes', { count: 5 }), value: 300000 },
{ name: I18n.t('user.auto_track_options.after_n_minutes', { count: 10 }), value: 600000 }],
{ name: I18n.t('user.auto_track_options.after_30_seconds'), value: 30000 },
{ name: I18n.t('user.auto_track_options.after_1_minute'), value: 60000 },
{ name: I18n.t('user.auto_track_options.after_2_minutes'), value: 120000 },
{ name: I18n.t('user.auto_track_options.after_3_minutes'), value: 180000 },
{ name: I18n.t('user.auto_track_options.after_4_minutes'), value: 240000 },
{ name: I18n.t('user.auto_track_options.after_5_minutes'), value: 300000 },
{ name: I18n.t('user.auto_track_options.after_10_minutes'), value: 600000 }],
considerNewTopicOptions: [{ name: I18n.t('user.new_topic_duration.not_viewed'), value: -1 },
{ name: I18n.t('user.new_topic_duration.after_n_days', { count: 1 }), value: 60 * 24 },
{ name: I18n.t('user.new_topic_duration.after_n_days', { count: 2 }), value: 60 * 48 },
{ name: I18n.t('user.new_topic_duration.after_n_weeks', { count: 1 }), value: 7 * 60 * 24 },
{ name: I18n.t('user.new_topic_duration.after_n_weeks', { count: 2 }), value: 2 * 7 * 60 * 24 },
{ name: I18n.t('user.new_topic_duration.after_1_day'), value: 60 * 24 },
{ name: I18n.t('user.new_topic_duration.after_2_days'), value: 60 * 48 },
{ name: I18n.t('user.new_topic_duration.after_1_week'), value: 7 * 60 * 24 },
{ name: I18n.t('user.new_topic_duration.after_2_weeks'), value: 2 * 7 * 60 * 24 },
{ name: I18n.t('user.new_topic_duration.last_here'), value: -2 }],
saveButtonText: function() {

View File

@ -312,6 +312,9 @@ td.flaggers td {
.setting-value {
float: left;
width: 53%;
.category-group {
width: 95%;
}
@media (max-width: $mobile-breakpoint) {
width: 100%;
}

View File

@ -0,0 +1,27 @@
require_dependency 'enum_site_setting'
class AutoTrackDurationSiteSetting < EnumSiteSetting
def self.valid_value?(val)
values.any? { |v| v[:value].to_s == val.to_s }
end
def self.values
@values ||= [
{ name: 'user.auto_track_options.never', value: -1 },
{ name: 'user.auto_track_options.immediately', value: 0 },
{ name: 'user.auto_track_options.after_30_seconds', value: 1000 * 30 },
{ name: 'user.auto_track_options.after_1_minute', value: 1000 * 60 },
{ name: 'user.auto_track_options.after_2_minutes', value: 1000 * 60 * 2 },
{ name: 'user.auto_track_options.after_3_minutes', value: 1000 * 60 * 3 },
{ name: 'user.auto_track_options.after_4_minutes', value: 1000 * 60 * 4 },
{ name: 'user.auto_track_options.after_5_minutes', value: 1000 * 60 * 5 },
{ name: 'user.auto_track_options.after_10_minutes', value: 1000 * 60 * 10 },
]
end
def self.translate_names?
true
end
end

View File

@ -0,0 +1,24 @@
require_dependency 'enum_site_setting'
class NewTopicDurationSiteSetting < EnumSiteSetting
def self.valid_value?(val)
values.any? { |v| v[:value].to_s == val.to_s }
end
def self.values
@values ||= [
{ name: 'user.new_topic_duration.not_viewed', value: -1 },
{ name: 'user.new_topic_duration.after_1_day', value: 60 * 24 },
{ name: 'user.new_topic_duration.after_2_days', value: 60 * 24 * 2 },
{ name: 'user.new_topic_duration.after_1_week', value: 60 * 24 * 7 },
{ name: 'user.new_topic_duration.after_2_weeks', value: 60 * 24 * 7 * 2 },
{ name: 'user.new_topic_duration.last_here', value: -2 },
]
end
def self.translate_names?
true
end
end

View File

@ -99,6 +99,14 @@ class SiteSetting < ActiveRecord::Base
false
end
def self.default_categories_selected
[
SiteSetting.default_categories_watching.split("|"),
SiteSetting.default_categories_tracking.split("|"),
SiteSetting.default_categories_muted.split("|"),
].flatten.to_set
end
end
# == Schema Information

View File

@ -110,7 +110,7 @@ class TopicTrackingState
now: DateTime.now,
last_visit: User::NewTopicDuration::LAST_VISIT,
always: User::NewTopicDuration::ALWAYS,
default_duration: SiteSetting.new_topic_duration_minutes
default_duration: SiteSetting.default_other_new_topic_duration_minutes
).where_values[0]
end

View File

@ -97,7 +97,7 @@ class TopicUser < ActiveRecord::Base
if rows == 0
now = DateTime.now
auto_track_after = User.select(:auto_track_topics_after_msecs).find_by(id: user_id).auto_track_topics_after_msecs
auto_track_after ||= SiteSetting.auto_track_topics_after
auto_track_after ||= SiteSetting.default_other_auto_track_topics_after_msecs
if auto_track_after >= 0 && auto_track_after <= (attrs[:total_msecs_viewed] || 0)
attrs[:notification_level] ||= notification_levels[:tracking]
@ -143,7 +143,7 @@ class TopicUser < ActiveRecord::Base
now: DateTime.now,
msecs: msecs,
tracking: notification_levels[:tracking],
threshold: SiteSetting.auto_track_topics_after
threshold: SiteSetting.default_other_auto_track_topics_after_msecs
}
# In case anyone seens "highest_seen_post_number" and gets confused, like I do.
@ -198,7 +198,7 @@ class TopicUser < ActiveRecord::Base
if rows.length == 0
# The user read at least one post in a topic that they haven't viewed before.
args[:new_status] = notification_levels[:regular]
if (user.auto_track_topics_after_msecs || SiteSetting.auto_track_topics_after) == 0
if (user.auto_track_topics_after_msecs || SiteSetting.default_other_auto_track_topics_after_msecs) == 0
args[:new_status] = notification_levels[:tracking]
end
TopicTrackingState.publish_read(topic_id, post_number, user.id, args[:new_status])

View File

@ -75,14 +75,15 @@ class User < ActiveRecord::Base
validates :ip_address, allowed_ip_address: {on: :create, message: :signup_not_allowed}
after_initialize :add_trust_level
after_initialize :set_default_email_digest
after_initialize :set_default_external_links_in_new_tab
before_create :set_default_user_preferences
after_create :create_email_token
after_create :create_user_stat
after_create :create_user_profile
after_create :ensure_in_trust_level_group
after_create :automatic_group_membership
after_create :set_default_categories_preferences
before_save :update_username_lower
before_save :ensure_password_is_hashed
@ -578,7 +579,7 @@ class User < ActiveRecord::Base
end
def treat_as_new_topic_start_date
duration = new_topic_duration_minutes || SiteSetting.new_topic_duration_minutes
duration = new_topic_duration_minutes || SiteSetting.default_other_new_topic_duration_minutes
[case duration
when User::NewTopicDuration::ALWAYS
created_at
@ -901,26 +902,42 @@ class User < ActiveRecord::Base
end
end
def set_default_email_digest
if has_attribute?(:email_digests) && self.email_digests.nil?
if SiteSetting.default_digest_email_frequency.blank?
self.email_digests = false
else
self.email_digests = true
self.digest_after_days ||= SiteSetting.default_digest_email_frequency.to_i if has_attribute?(:digest_after_days)
end
end
def set_default_user_preferences
set_default_email_digest_frequency
set_default_email_private_messages
set_default_email_direct
set_default_email_mailing_list_mode
set_default_email_always
set_default_other_new_topic_duration_minutes
set_default_other_auto_track_topics_after_msecs
set_default_other_external_links_in_new_tab
set_default_other_enable_quoting
set_default_other_dynamic_favicon
set_default_other_disable_jump_reply
set_default_other_edit_history_public
# needed, otherwise the callback chain is broken...
true
end
def set_default_external_links_in_new_tab
if has_attribute?(:external_links_in_new_tab) && self.external_links_in_new_tab.nil?
self.external_links_in_new_tab = !SiteSetting.default_external_links_in_new_tab.blank?
def set_default_categories_preferences
values = []
%w{watching tracking muted}.each do |s|
category_ids = SiteSetting.send("default_categories_#{s}").split("|")
category_ids.each do |category_id|
values << "(#{self.id}, #{category_id}, #{CategoryUser.notification_levels[s.to_sym]})"
end
end
if values.present?
exec_sql("INSERT INTO category_users (user_id, category_id, notification_level) VALUES #{values.join(",")}")
end
end
# Delete unactivated accounts (without verified email) that are over a week old
def self.purge_unactivated
to_destroy = User.where(active: false)
.joins('INNER JOIN user_stats AS us ON us.user_id = users.id')
.where("created_at < ?", SiteSetting.purge_unactivated_users_grace_period_days.days.ago)
@ -950,6 +967,39 @@ class User < ActiveRecord::Base
end
end
def set_default_email_digest_frequency
if has_attribute?(:email_digests)
if SiteSetting.default_email_digest_frequency.blank?
self.email_digests = false
else
self.email_digests = true
self.digest_after_days ||= SiteSetting.default_email_digest_frequency.to_i if has_attribute?(:digest_after_days)
end
end
end
def set_default_email_mailing_list_mode
self.mailing_list_mode = SiteSetting.default_email_mailing_list_mode if has_attribute?(:mailing_list_mode)
end
%w{private_messages direct always}.each do |s|
define_method("set_default_email_#{s}") do
self.send("email_#{s}=", SiteSetting.send("default_email_#{s}")) if has_attribute?("email_#{s}")
end
end
%w{new_topic_duration_minutes auto_track_topics_after_msecs}.each do |s|
define_method("set_default_other_#{s}") do
self.send("#{s}=", SiteSetting.send("default_other_#{s}").to_i) if has_attribute?(s)
end
end
%w{external_links_in_new_tab enable_quoting dynamic_favicon disable_jump_reply edit_history_public}.each do |s|
define_method("set_default_other_#{s}") do
self.send("#{s}=", SiteSetting.send("default_other_#{s}")) if has_attribute?(s)
end
end
end
# == Schema Information

View File

@ -249,11 +249,11 @@ class UserSerializer < BasicUserSerializer
###
def auto_track_topics_after_msecs
object.auto_track_topics_after_msecs || SiteSetting.auto_track_topics_after
object.auto_track_topics_after_msecs || SiteSetting.default_other_auto_track_topics_after_msecs
end
def new_topic_duration_minutes
object.new_topic_duration_minutes || SiteSetting.new_topic_duration_minutes
object.new_topic_duration_minutes || SiteSetting.default_other_new_topic_duration_minutes
end
def muted_category_ids

View File

@ -583,23 +583,22 @@ en:
label: "Consider topics new when"
not_viewed: "I haven't viewed them yet"
last_here: "created since I was here last"
after_n_days:
one: "created in the last day"
other: "created in the last {{count}} days"
after_n_weeks:
one: "created in the last week"
other: "created in the last {{count}} weeks"
after_1_day: "created in the last day"
after_2_days: "created in the last 2 days"
after_1_week: "created in the last week"
after_2_weeks: "created in the last 2 weeks"
auto_track_topics: "Automatically track topics I enter"
auto_track_options:
never: "never"
immediately: "immediately"
after_n_seconds:
one: "after 1 second"
other: "after {{count}} seconds"
after_n_minutes:
one: "after 1 minute"
other: "after {{count}} minutes"
after_30_seconds: "after 30 seconds"
after_1_minute: "after 1 minute"
after_2_minutes: "after 2 minutes"
after_3_minutes: "after 3 minutes"
after_4_minutes: "after 4 minutes"
after_5_minutes: "after 5 minutes"
after_10_minutes: "after 10 minutes"
invited:
search: "type to search invites..."
@ -2422,6 +2421,7 @@ en:
backups: "Backups"
login: "Login"
plugins: "Plugins"
user_preferences: "User Preferences"
badges:
title: Badges

View File

@ -698,8 +698,8 @@ bs_BA:
automatically_download_gravatars: "Download Gravatars for users upon account creation or email change."
digest_topics: "The maximum number of topics to display in the email digest."
digest_min_excerpt_length: "Minimum post excerpt in the email digest, in characters."
default_digest_email_frequency: "How often users receive digest emails by default. They can change this setting in their preferences."
default_external_links_in_new_tab: "Open external links in a new tab. Users can change this in their preferences."
default_email_digest_frequency: "How often users receive digest emails by default. They can change this setting in their preferences."
default_other_external_links_in_new_tab: "Open external links in a new tab. Users can change this in their preferences."
max_daily_gravatar_crawls: "Maximum number of times Discourse will check Gravatar for custom avatars in a day"
public_user_custom_fields: "A whitelist of custom fields for a user that can be shown publically."
allow_profile_backgrounds: "Allow users to upload profile backgrounds."

View File

@ -668,8 +668,8 @@ cs:
delete_all_posts_max: "Maximální počet příspěvků, které mohou být smazány najednou tlačítkem 'Odstranit všechny příspěvky'. Pokud má uživatel více příspěvků než je zde nastaveno, nemohou být jeho příspěvky smazány najednou a uživatele nelze odstranit."
username_change_period: "Počet dní od registrace za kolik si uživatel může změnit svoje uživatelské jméno (0 pokud chcete změnu uživatelského jména úplně zakázat)."
email_editable: "Povolit uživatelům změnit si po registraci emailovou adresu."
default_digest_email_frequency: "How often users receive digest emails by default. They can change this setting in their preferences."
default_external_links_in_new_tab: "Otevírat odkazy na externí weby v novém tabu. Uživatelé si toto můžou změnit v svém nastavení."
default_email_digest_frequency: "How often users receive digest emails by default. They can change this setting in their preferences."
default_other_external_links_in_new_tab: "Otevírat odkazy na externí weby v novém tabu. Uživatelé si toto můžou změnit v svém nastavení."
enable_mobile_theme: "Používat na mobilních zařízeních verzi přizpůsobenou pro mobily s možností přejít na plnou verzi. Zruště pokud chcete používat vlastní plně responzivní kaskádový styl."
short_progress_text_threshold: "After the number of posts in a topic goes above this number, the progress bar will only show the current post number. If you change the progress bar's width, you may need to change this value."
default_code_lang: "Default programming language syntax highlighting applied to GitHub code blocks (lang-auto, ruby, python etc.)"

View File

@ -626,8 +626,8 @@ da:
delete_all_posts_max: "Det maksimale antal indlæg der kan slettes på én gang med “Slet alle indlæg”-knappen. Hvis en bruger har mere end dette antal indlæg, kan indlæggene ikke slettes på én gang og brugeren kan ikke slettes."
username_change_period: "Antal dage efter oprettelsen hvor brugere kan ændre deres brugernavn (0 for ikke at tillade skift af brugernavn)."
email_editable: "Lad brugerne skifte deres e-mail-adresse efter oprettelsen."
default_digest_email_frequency: "Hvor ofte brugerne som standard modtager e-mail-sammendrag. De kan ændre indstillingen på deres profil."
default_external_links_in_new_tab: "Åbn eksterne links i en nu fane; brugerne kan ændre dette på deres profil"
default_email_digest_frequency: "Hvor ofte brugerne som standard modtager e-mail-sammendrag. De kan ændre indstillingen på deres profil."
default_other_external_links_in_new_tab: "Åbn eksterne links i en nu fane; brugerne kan ændre dette på deres profil"
enable_mobile_theme: "Mobile enheder bruger et mobilvenligt tema, med mulighed for at skifte til det fulde site. Deaktivér dette hvis du ønsker at anvende et brugerdefineret stylesheet som er fuldstændigt responsivt."
short_progress_text_threshold: "Når antallet af indlæg overstiger dette tal viser statuslinjen kun det aktuelle indlægsnummer. Hvis du ændrer bredden af statuslinjen kan det være nødvendigt at opdatere denne værdi."
default_code_lang: "Standard syntax highlighting som bruges i GitHub kodeblokke (lang-auto, ruby, python etc.)."

View File

@ -912,10 +912,10 @@ de:
automatically_download_gravatars: "Avatare von Gravatar herunterladen, wenn ein Nutzer sich registriert oder seine E-Mail-Adresse ändert."
digest_topics: "Maximale Anzahl von Themen, die in der E-Mail-Zusammenfassung angezeigt werden."
digest_min_excerpt_length: "Minimale Länge des Auszugs aus einem Beitrag in der E-Mail-Zusammenfassung, in Zeichen."
default_digest_email_frequency: "Wie oft man Zusammenfassungen per Mail standardmässig erhält. Diese Einstellung kann von jedem geändert werden."
default_email_digest_frequency: "Wie oft man Zusammenfassungen per Mail standardmässig erhält. Diese Einstellung kann von jedem geändert werden."
suppress_digest_email_after_days: "Sende keine E-Mail-Zusammenfassungen an Benutzer, die die Seite seit mehr als (n) Tagen nicht mehr besucht haben."
disable_digest_emails: "E-Mail-Zusammenfassungen für alle Benutzer deaktivieren."
default_external_links_in_new_tab: "Öffne externe Links in einem neuen Tab. Benutzer können dies in ihren Einstellungen ändern."
default_other_external_links_in_new_tab: "Öffne externe Links in einem neuen Tab. Benutzer können dies in ihren Einstellungen ändern."
max_daily_gravatar_crawls: "Wie oft pro Tag Discourse höchstens auf Gravatar nach benuterdefinierten Avataren suchen soll."
public_user_custom_fields: "Liste selbst definierter Profil-Felder, die öffentlich angezeigt werden dürfen."
staff_user_custom_fields: "Liste selbst definierter Profil-Felder, die Mitarbeitern angezeigt werden dürfen."

View File

@ -95,6 +95,7 @@ en:
min_username_length_range: "You cannot set the minimum above the maximum."
max_username_length_exists: "You cannot set the maximum username length below the longest username."
max_username_length_range: "You cannot set the maximum above the minimum."
default_categories_already_selected: "You cannot select a category used in another list."
activemodel:
errors:
@ -829,9 +830,6 @@ en:
anon_polling_interval: "How often should anonymous clients poll in milliseconds"
background_polling_interval: "How often should the clients poll in milliseconds (when the window is in the background)"
auto_track_topics_after: "Global default milliseconds before a topic is automatically tracked, users can override (0 for always, -1 for never)"
new_topic_duration_minutes: "Global default number of minutes a topic is considered new, users can override (-1 for always, -2 for last visit)"
flags_required_to_hide_post: "Number of flags that cause a post to be automatically hidden and PM sent to the user (0 for never)"
cooldown_minutes_after_hiding_posts: "Number of minutes a user must wait before they can edit a post hidden via community flagging"
@ -1124,10 +1122,8 @@ en:
automatically_download_gravatars: "Download Gravatars for users upon account creation or email change."
digest_topics: "The maximum number of topics to display in the email digest."
digest_min_excerpt_length: "Minimum post excerpt in the email digest, in characters."
default_digest_email_frequency: "How often users receive digest emails by default. They can change this setting in their preferences."
suppress_digest_email_after_days: "Suppress digest emails for users not seen on the site for more than (n) days."
disable_digest_emails: "Disable digest emails for all users."
default_external_links_in_new_tab: "Open external links in a new tab. Users can change this in their preferences."
detect_custom_avatars: "Whether or not to check that users have uploaded custom profile pictures."
max_daily_gravatar_crawls: "Maximum number of times Discourse will check Gravatar for custom avatars in a day"
@ -1195,6 +1191,24 @@ en:
approve_unless_trust_level: "Posts for users below this trust level must be approved"
notify_about_queued_posts_after: "If there are posts that have been waiting to be reviewed for more than this many hours, an email will be sent to the contact email. Set to 0 to disable these emails."
default_email_digest_frequency: "How often users receive digest emails by default."
default_email_private_messages: "Send an email when someone messages the user by default."
default_email_direct: "Send an email when someone quotes/replies to/mentions or invites the user by default."
default_email_mailing_list_mode: "Send an email for every new post by default."
default_email_always: "Send an email notification even when the user is active by default."
default_other_new_topic_duration_minutes: "Global default number of minutes a topic is considered new, users can override (-1 for always, -2 for last visit)"
default_other_auto_track_topics_after_msecs: "Global default milliseconds before a topic is automatically tracked, users can override (0 for always, -1 for never)"
default_other_external_links_in_new_tab: "Open external links in a new tab by default."
default_other_enable_quoting: "Enable quote reply for highlighted text by default."
default_other_dynamic_favicon: "Show new/updated topic count on browser icon by default."
default_other_disable_jump_reply: "Don't jump to user's post after they reply by default."
default_other_edit_history_public: "Make the post revisions public by default."
default_categories_watching: "List of categories that are watched by default."
default_categories_tracking: "List of categories that are tracked by default."
default_categories_muted: "List of categories that are muted by default."
errors:
invalid_email: "Invalid email address."
invalid_username: "There's no user with that username."

View File

@ -962,10 +962,10 @@ es:
automatically_download_gravatars: "Descargar Gravatars para usuarios cuando se creen una cuenta o cambien el email."
digest_topics: "El número máximo de temas a mostrar en el resumen por email."
digest_min_excerpt_length: "La extensión mínima, en caracteres, del extracto de un post en el resumen por email."
default_digest_email_frequency: "Cada cuánto tiempo los usuarios recibirán emails con el resumen del sitio por defecto. Cada usuario puede cambiar esta opción para sí en sus preferencias."
default_email_digest_frequency: "Cada cuánto tiempo los usuarios recibirán emails con el resumen del sitio por defecto. Cada usuario puede cambiar esta opción para sí en sus preferencias."
suppress_digest_email_after_days: "Suprimir los emails de resumen para aquellos usuarios que no han visto el sitio desde más de (n) días."
disable_digest_emails: "Inhabilitar e-mails de resumen para todos los usuarios."
default_external_links_in_new_tab: "Abrir enlaces externos en una nueva pestaña. Los usuarios pueden cambiar esto en sus preferencias."
default_other_external_links_in_new_tab: "Abrir enlaces externos en una nueva pestaña. Los usuarios pueden cambiar esto en sus preferencias."
detect_custom_avatars: "Verificar o no que los usuarios han subido una imagen de perfil."
max_daily_gravatar_crawls: "Máximo número de veces que Discourse comprobará Gravatar en busca de avatares personalizados en un día"
public_user_custom_fields: "Una lista con campos personalizados para el usuario que pueden ser mostrados públicamente."

View File

@ -903,10 +903,10 @@ fa_IR:
automatically_download_gravatars: "آواتار را برای کاربران دریافت کن برای ساختن حساب کاربری یا ایمیل. "
digest_topics: "حداکثر تعداد جستارهایی که در دایجست ایمیل نشان داده می شود "
digest_min_excerpt_length: "حداقل نوشته های گزیده در ایمیل دایجست٬‌ در کاراکتر."
default_digest_email_frequency: "هر چند وقت یکبار کاربران ایمیل های دایجست دریافت کنند بطور پیش فرض. آنها می توانند آن را در بخش تنظیمات عوض کنند. "
default_email_digest_frequency: "هر چند وقت یکبار کاربران ایمیل های دایجست دریافت کنند بطور پیش فرض. آنها می توانند آن را در بخش تنظیمات عوض کنند. "
suppress_digest_email_after_days: "ایمیل های خلاصه را مهار کن برای کاربرانی که در وب سایت دیده نشده اند بیشتر از (n) روز "
disable_digest_emails: "ایمیل های دایجست را برای تمام کاربران غیر فعال کن. "
default_external_links_in_new_tab: "پیوند های خارجی را در یک تب جدید باز کن. کاربران می توانند این را در قسمت تنظیماتشان تغییر دهند."
default_other_external_links_in_new_tab: "پیوند های خارجی را در یک تب جدید باز کن. کاربران می توانند این را در قسمت تنظیماتشان تغییر دهند."
max_daily_gravatar_crawls: "حداکثرتعداد زمانی که دیسکورس Gravatar را چک می کند برای آواتار سفارشی در هر روز. "
public_user_custom_fields: "لیست مجاز فیلد سفارشی برای کاربر که می تواند به همه نشان داده شود."
staff_user_custom_fields: "لیست مجاز فیلد سفارشی برای کاربر که می تواند به مدیران نشان داده شود."

View File

@ -971,10 +971,10 @@ fi:
automatically_download_gravatars: "Lataa käyttäjille Gravatarit automaattisesti tilin luonnin ja sähköpostin vaihdon yhteydessä."
digest_topics: "Sähköpostitiivistelmässä näytettävien ketjujen maksimimäärä."
digest_min_excerpt_length: "Viestin katkelman vähimmäispituus sähköpostitiivistelmässä, merkeissä"
default_digest_email_frequency: "Kuinka usein käyttäjän saavat sähköpostitiivistelmän oletuksena. He voivat muuttaa asetusta omista asetuksistaan."
default_email_digest_frequency: "Kuinka usein käyttäjän saavat sähköpostitiivistelmän oletuksena. He voivat muuttaa asetusta omista asetuksistaan."
suppress_digest_email_after_days: "Jätä lähettämättä tiivistelmäsähköpostit käyttäjille, joita ei ole nähty (n) päivän aikana."
disable_digest_emails: "Ota tiivistelmäsähköpostit pois käytöstä kaikilta käyttäjiltä."
default_external_links_in_new_tab: "Avaa ulkoiset linkit uudessa välilehdessä. Käyttäjät voivat muuttaa tämän asetuksistaan."
default_other_external_links_in_new_tab: "Avaa ulkoiset linkit uudessa välilehdessä. Käyttäjät voivat muuttaa tämän asetuksistaan."
detect_custom_avatars: "Tarkistetaanko, ovatko käyttäjät ladanneet oman profiilikuvan."
max_daily_gravatar_crawls: "Korkeintaan kuinka monta kertaa Discourse tarkistaa avatarit Gravatarista päivässä"
public_user_custom_fields: "Whitelist käyttäjän mukautetuista kentistä, jotka voidaan näyttää julkisesti."

View File

@ -966,10 +966,10 @@ fr:
automatically_download_gravatars: "Télécharger les gravatars pour les utilisateurs lors de la création de compte ou de la modification de courriel."
digest_topics: "Nombre maximum de sujets à afficher dans le courriel de résumé."
digest_min_excerpt_length: "Taille minimum du résumé des messages dans les courriels, en caractères."
default_digest_email_frequency: "A quelle fréquence les utilisateurs reçoivent-ils les courriels par défaut. Ils peuvent modifier ce paramétrage dans leur préférences."
default_email_digest_frequency: "A quelle fréquence les utilisateurs reçoivent-ils les courriels par défaut. Ils peuvent modifier ce paramétrage dans leur préférences."
suppress_digest_email_after_days: "Ne pas envoyer de résumés courriel aux utilisateurs qui n'ont pas visité le site depuis (n) jours."
disable_digest_emails: "Désactiver les résumés par courriels pour tous les utilisateurs."
default_external_links_in_new_tab: "Les liens externes s'ouvrent dans un nouvel onglet. Les utilisateurs peuvent modifier ceci dans leurs préférences."
default_other_external_links_in_new_tab: "Les liens externes s'ouvrent dans un nouvel onglet. Les utilisateurs peuvent modifier ceci dans leurs préférences."
detect_custom_avatars: "Vérifier ou non si les utilisateurs ont envoyé une photo de profil personnalisée."
max_daily_gravatar_crawls: "Nombre maximum de fois que Discourse vérifiera Gravatar pour des avatars personnalisés en une journée."
public_user_custom_fields: "Une liste blanche des champs personnalisés pour un utilisateur qui peuvent être affichés publiquement."

View File

@ -950,10 +950,10 @@ he:
automatically_download_gravatars: "הורדת גראווטרים למשתמשים בעת יצירת החשבון או שינוי כתובת הדוא\"ל."
digest_topics: "מספר הנושאים המקסימלי להצגה במייל סיכום."
digest_min_excerpt_length: "מספר התווים המינימלי למובאות מתוך הפרסום במייל הסיכום."
default_digest_email_frequency: "How often users receive digest emails by default. They can change this setting in their preferences."
default_email_digest_frequency: "How often users receive digest emails by default. They can change this setting in their preferences."
suppress_digest_email_after_days: "השהיית מיילים מסכמים עבור משתמשים שלא נראו באתר במשך יותר מ(n) ימים."
disable_digest_emails: "נטרול דוא\"ל סיכום לכל המשתמשים."
default_external_links_in_new_tab: "Open external links in a new tab. Users can change this in their preferences."
default_other_external_links_in_new_tab: "Open external links in a new tab. Users can change this in their preferences."
detect_custom_avatars: "Whether or not to check that users have uploaded custom profile pictures."
max_daily_gravatar_crawls: "מספר הפעמים המקסימלי ש-Discourse יבדוק אווטרים ב-Gravatar ביום"
public_user_custom_fields: "רשימה לבנה (whitelist) של שדות מותאמים למשתמש שיכולים להיות מוצגים באופן פומבי."

View File

@ -896,8 +896,8 @@ it:
default_avatars: "URL degli avatar che verranno utilizzati come predefiniti per tutti i nuovi utenti, fintanto che non li cambieranno esplicitamente."
automatically_download_gravatars: "Scarica i Gravatars per gli utenti quando viene creato l'account o quando viene modificata l'email"
digest_topics: "Numero massimo di argomenti da mostrare nel riassunto email."
default_digest_email_frequency: "Quanto spesso gli utenti ricevono email di riepilogo. Gli utenti possono modificare questa impostazione nelle loro preferenze."
default_external_links_in_new_tab: "Apri i collegamenti esterni in una nuova scheda. Gli utenti possono modificare questa impostazione nelle loro preferenze."
default_email_digest_frequency: "Quanto spesso gli utenti ricevono email di riepilogo. Gli utenti possono modificare questa impostazione nelle loro preferenze."
default_other_external_links_in_new_tab: "Apri i collegamenti esterni in una nuova scheda. Gli utenti possono modificare questa impostazione nelle loro preferenze."
allow_profile_backgrounds: "Permetti agli utenti di caricare immagini di sfondo per il profilo."
enable_mobile_theme: "I dispositivi mobili usano un tema apposito, con possibilità di passare alla visualizzazione completa. Disabilita questa opzione se vuoi usare un foglio di stile personalizzato che sia completamente reattivo."
suppress_uncategorized_badge: "Non mostrare la targhetta per gli argomenti senza categoria nell'elenco degli argomenti."

View File

@ -897,10 +897,10 @@ ja:
automatically_download_gravatars: "アカウントの生成時、メールアドレスの変更時にGravatarをダウンロード"
digest_topics: "ダイジェストメールに表示されるトピックの最大数"
digest_min_excerpt_length: "ダイジェストメール内の投稿の抜粋の最小文字数"
default_digest_email_frequency: "ユーザがダイジェストメールを受け取る頻度のデフォルト値。ユーザは設定画面でこの値をカスタマイズできます。"
default_email_digest_frequency: "ユーザがダイジェストメールを受け取る頻度のデフォルト値。ユーザは設定画面でこの値をカスタマイズできます。"
suppress_digest_email_after_days: "(n)日以上ユーザが参照していなければダイジェストメールを抑制します"
disable_digest_emails: "全てのユーザのダイジェストメールを無効にする"
default_external_links_in_new_tab: "外部リンクは新しいタブで開きます。ユーザーはこの設定を変更する事が出来ます"
default_other_external_links_in_new_tab: "外部リンクは新しいタブで開きます。ユーザーはこの設定を変更する事が出来ます"
detect_custom_avatars: "ユーザがプロフィール画像をアップロードしたか確認する"
max_daily_gravatar_crawls: "Discourseがプロフィール画像の確認をgravastarに行う回数の上限"
public_user_custom_fields: "パブリックに公開されるカスタムフィールドのホワイトリスト"

View File

@ -886,10 +886,10 @@ ko:
automatically_download_gravatars: "사용자가 계정을 만들거나 이메일을 변경하자마자 Gravatar를 다운로드합니다."
digest_topics: "요약 이메일에서 보여질 최대 토픽 개수"
digest_min_excerpt_length: "요약 이메일에서 최소 포스트 발췌 수"
default_digest_email_frequency: "사용자가 요약 이메일을 받는 횟수 기본값. 사용자는 그들의 환경설정에서 변경할 수 있음"
default_email_digest_frequency: "사용자가 요약 이메일을 받는 횟수 기본값. 사용자는 그들의 환경설정에서 변경할 수 있음"
suppress_digest_email_after_days: "(n)일동안 사이트에서 보지 못한 사용자에게는 이메일 요약을 보내지 않습니다."
disable_digest_emails: "모든 유저들 이메일 다이제스트 못하게 하기"
default_external_links_in_new_tab: "다른 싸이트의 링크는 새 탭으로 연다. 사용자는 자신의 설정에 따라 바꿀 수 있음"
default_other_external_links_in_new_tab: "다른 싸이트의 링크는 새 탭으로 연다. 사용자는 자신의 설정에 따라 바꿀 수 있음"
max_daily_gravatar_crawls: "하루에 Discourse가 커스텀 아파타를 위해 Gravatar를 체크하는 최대 횟수"
public_user_custom_fields: "유저가 쓸 수 있는 공개 커스텀 필드 목록"
staff_user_custom_fields: "스태프가 쓸 수 있는 공개 커스텀 필드 목록"

View File

@ -840,8 +840,8 @@ nl:
email_editable: "Gebruikers mogen hun e-mailadres na registratie nog wijzigen."
digest_topics: "Het maximum aantal topics dat in de e-maildigest opgenomen wordt."
digest_min_excerpt_length: "Hoeveel karakters er per bericht getoond worden in de mail digest"
default_digest_email_frequency: "Hoe vaak ontvangen gebruikers standaard de digestmails. Ze kunnen dit in hun eigen instellingen nog aanpassen."
default_external_links_in_new_tab: "Open externe links in a nieuwe tab. Gebruikers kunnen dit wijzigen in hun instellingen."
default_email_digest_frequency: "Hoe vaak ontvangen gebruikers standaard de digestmails. Ze kunnen dit in hun eigen instellingen nog aanpassen."
default_other_external_links_in_new_tab: "Open externe links in a nieuwe tab. Gebruikers kunnen dit wijzigen in hun instellingen."
allow_profile_backgrounds: "Gebruikers mogen een profielachtergrond instellen."
enable_mobile_theme: "Mobiele apparaten gebruiken een mobiel-vriendelijke theme met de mogelijkheid te schakelen naar de volledige site. Schakel deze optie uit als je een eigen stylesheet wil gebruiken die volledig responsive is."
suppress_uncategorized_badge: "Laat de badge niet zien voor topics zonder categorie in de topiclijsten."

View File

@ -796,10 +796,10 @@ pl_PL:
email_editable: "Allow users to change their e-mail address after registration."
digest_topics: "Maksymalna liczba tematów w podsumowaniu e-mail."
digest_min_excerpt_length: "Minimalny wycinek wpisu (liczba znaków) w podsumowaniu e-mail."
default_digest_email_frequency: "How often users receive digest emails by default. They can change this setting in their preferences."
default_email_digest_frequency: "How often users receive digest emails by default. They can change this setting in their preferences."
suppress_digest_email_after_days: "Nie wysyłaj podsumowań e-mail użytkownikom, którzy nie odwiedzili serwisu dłużej niż (n) dni."
disable_digest_emails: "Wyłącz wysyłanie podsumowania e-mail wszystkim uzytkownikom. "
default_external_links_in_new_tab: "Otwieraj zewnętrzne odnośniki w nowej karcie. Użytkownicy mogą zmienić to ustawienie w swoich preferencjach."
default_other_external_links_in_new_tab: "Otwieraj zewnętrzne odnośniki w nowej karcie. Użytkownicy mogą zmienić to ustawienie w swoich preferencjach."
allow_profile_backgrounds: "Zezwól użytkownikom na przesyłanie obrazu tła dla profilu."
enable_mobile_theme: "Urządzenia mobilne używają dedykowanego mobilnego szablonu. Wyłącz to, jeśli chcesz użyć własnego, pojedynczego i responsywnego szablonu stylów. "
suppress_uncategorized_badge: "Nie pokazuj etykiety z nazwą kategorii Inne na listach tematów."

View File

@ -975,10 +975,10 @@ pt:
automatically_download_gravatars: "Descarregar Gravatars para os utilizadores após criação de conta ou mudança de email."
digest_topics: "Número máximo de tópicos a serem apresentados no resumo do email."
digest_min_excerpt_length: "Tamanho mínimo do excerto da mensagem no resumo do email, em caracteres."
default_digest_email_frequency: "Por defeito, quantas vezes os utilizadores recebem emails de resumo. Os utilizadores podem alterar esta configuração nas suas preferências."
default_email_digest_frequency: "Por defeito, quantas vezes os utilizadores recebem emails de resumo. Os utilizadores podem alterar esta configuração nas suas preferências."
suppress_digest_email_after_days: "Suprimir emails de resumos para utilizadores não vistos no sítio por mais de (n) dias."
disable_digest_emails: "Desativar os emails de resumo para todos os utilizadores."
default_external_links_in_new_tab: "Abrir hiperligações externas num novo separador. Os utilizadores podem alterar isto nas suas preferências."
default_other_external_links_in_new_tab: "Abrir hiperligações externas num novo separador. Os utilizadores podem alterar isto nas suas preferências."
detect_custom_avatars: "Se deve ou não verificar que os utilizadores carregaram fotografias de perfil personalizadas."
max_daily_gravatar_crawls: "Número máximo de vezes que o Discourse irá verificar o Gravatar para avatars personalizados, por dia"
public_user_custom_fields: "Lista de campos personalizados para um utilizador e que podem ser exibidos publicamente."

View File

@ -938,10 +938,10 @@ pt_BR:
automatically_download_gravatars: "Fazer download de Gravatars dos usuários ao criar conta ou mudança de email."
digest_topics: "O número máximo de tópicos a serem mostrados no resumo via email."
digest_min_excerpt_length: "O excerto mínimo de post no resumo via email, em caracteres."
default_digest_email_frequency: "Quantas vezes os usuários recebem emails de resumo por padrão. Eles podem alterar essa configuração em suas preferências."
default_email_digest_frequency: "Quantas vezes os usuários recebem emails de resumo por padrão. Eles podem alterar essa configuração em suas preferências."
suppress_digest_email_after_days: "Suprimir emails de resumo para usuários não vistos no site há mais do que (n) dias."
disable_digest_emails: "Desabilitar emails de resumo para todos os usuários."
default_external_links_in_new_tab: "Abrir links externos em uma nova guia. Os usuários podem mudar isso em suas preferências."
default_other_external_links_in_new_tab: "Abrir links externos em uma nova guia. Os usuários podem mudar isso em suas preferências."
max_daily_gravatar_crawls: "Número máximo de vezes que o Discourse irá checar o Gravatar por avatares personalizados em um dia"
public_user_custom_fields: "Um conjunto de campos personalizados para um usuário que podem ser apresentados publicamente."
staff_user_custom_fields: "Um conjunto de campos personalizados para um usuário que pode ser mostrado para membros da equipe."

View File

@ -770,7 +770,7 @@ ro:
automatically_download_gravatars: "Descarcă Gravatare pentru utilizatori la crearea contului sau schimbarea email-ului."
digest_topics: "Numărul maxim de discuții arătate în email-ul rezumat."
digest_min_excerpt_length: "Numărul minimum de extrase din postări din email-ul rezumat, în caractere."
default_digest_email_frequency: "Cat de des utliziatorii primesc emailuri rezumat din oficiu. Utilizatorii pot schimba această opțiune în preferințe."
default_email_digest_frequency: "Cat de des utliziatorii primesc emailuri rezumat din oficiu. Utilizatorii pot schimba această opțiune în preferințe."
max_daily_gravatar_crawls: "Numărul maxim de verificări făcute de Discourse pentru existența unui gravatar preferențial într-o zi"
allow_profile_backgrounds: "Permite utilizatorilor să încarce fundaluri de profil."
sequential_replies_threshold: "Numărul de postări la rând într-o discuție până să-i fie amintit utilizatorului că sunt prea multe răspunsuri secvențiale. "

View File

@ -986,10 +986,10 @@ ru:
automatically_download_gravatars: "Скачивать аватарку Gravatar пользователя во время создания учетной записи или изменения e-mail."
digest_topics: "Максимальное количество тем в письме - сводке новостей."
digest_min_excerpt_length: "Минимальная длина (в символах) вытяжки из сообщения в письме - сводке новостей."
default_digest_email_frequency: "Как часто пользователи получают дайджест по умолчанию. Возможно изменение этой настройки каждым пользователем."
default_email_digest_frequency: "Как часто пользователи получают дайджест по умолчанию. Возможно изменение этой настройки каждым пользователем."
suppress_digest_email_after_days: "Не рассылать новости для пользователей, которые не заходили на сайт в течении (n) дней."
disable_digest_emails: "Отключить рассылку новостей для всех пользователей."
default_external_links_in_new_tab: "Открывать внешние ссылки в новом окне. Пользователи могут изменить данное поведение в настройках."
default_other_external_links_in_new_tab: "Открывать внешние ссылки в новом окне. Пользователи могут изменить данное поведение в настройках."
max_daily_gravatar_crawls: "Максимальное количество загрузок аватаорок с Gravatar за один день"
public_user_custom_fields: "Список разрешенных дополнительных полей пользователей, которые могут быть отображены публично."
staff_user_custom_fields: "Список разрешенных дополнительных полей пользователей, которые могут быть отображены для модераторов."

View File

@ -971,10 +971,10 @@ sq:
automatically_download_gravatars: "Download Gravatars for users upon account creation or email change."
digest_topics: "The maximum number of topics to display in the email digest."
digest_min_excerpt_length: "Minimum post excerpt in the email digest, in characters."
default_digest_email_frequency: "How often users receive digest emails by default. They can change this setting in their preferences."
default_email_digest_frequency: "How often users receive digest emails by default. They can change this setting in their preferences."
suppress_digest_email_after_days: "Suppress digest emails for users not seen on the site for more than (n) days."
disable_digest_emails: "Disable digest emails for all users."
default_external_links_in_new_tab: "Open external links in a new tab. Users can change this in their preferences."
default_other_external_links_in_new_tab: "Open external links in a new tab. Users can change this in their preferences."
detect_custom_avatars: "Whether or not to check that users have uploaded custom profile pictures."
max_daily_gravatar_crawls: "Maximum number of times Discourse will check Gravatar for custom avatars in a day"
public_user_custom_fields: "A whitelist of custom fields for a user that can be shown publicly."

View File

@ -719,7 +719,7 @@ sv:
disable_emails: "Förhindra Discourse från att skicka någon form av e-post"
pop3_polling_ssl: "Använd SSL vid anslutning till POP3-servern. (Rekommenderat)"
email_editable: "Tillåt användare att ändra deras e-postadress efter registrering."
default_digest_email_frequency: "Hur ofta användare får emailutskick som standard. De kan ändra detta val under sina inställningar."
default_email_digest_frequency: "Hur ofta användare får emailutskick som standard. De kan ändra detta val under sina inställningar."
enable_user_directory: "Tillhandahåll en bläddringsbar användarkatalog"
allow_anonymous_posting: "Tillåt användare att växla till anonymt läge"
anonymous_posting_min_trust_level: "Lägsta förtroendenivå som krävs för att aktivera anonyma inlägg"

View File

@ -889,10 +889,10 @@ tr_TR:
automatically_download_gravatars: "Hesap oluşturma veya e-posta değişikliği esnasında kullanıcılar için Gravatarları indir"
digest_topics: "Özet e-postalarda yer alacak en fazla konu sayısı. "
digest_min_excerpt_length: "Özet e-postalarında, gönderi alıntılarında olması gereken en az karakter sayısı."
default_digest_email_frequency: "Varsayılan olarak, özet e-postalar hangi sıklıkta gönderilsin? Üyeler, ayarlar sayfasından bu değeri değiştirebilir."
default_email_digest_frequency: "Varsayılan olarak, özet e-postalar hangi sıklıkta gönderilsin? Üyeler, ayarlar sayfasından bu değeri değiştirebilir."
suppress_digest_email_after_days: "Siteye (n) günden fazla süredir uğramayan kullanıcılar için özet e-posta gönderimini durdur"
disable_digest_emails: "Tüm kullanıcılar için özet e-postalarını devre dışı bırak."
default_external_links_in_new_tab: "Dış bağlantıları yeni sekmede aç. Üyeler, ayarlar sayfasından bu ayarı değiştirebilir."
default_other_external_links_in_new_tab: "Dış bağlantıları yeni sekmede aç. Üyeler, ayarlar sayfasından bu ayarı değiştirebilir."
max_daily_gravatar_crawls: "Discourse'un gün içinde özel avatarlar için Gravatar'ı en fazla kaç kere kontrol edeceği."
public_user_custom_fields: "Kullanıcıların için, herkes tarafından görüntülenebilir özel alanların beyaz listesi."
staff_user_custom_fields: "Kullanıcıların için, sadece görevlilere görüntülenebilir özel alanların beyaz listesi."

View File

@ -371,8 +371,8 @@ uk:
delete_all_posts_max: "Максимальне число дописів, які можна видалити за один раз кнопкою \"Видалити всі дописи\". Якщо користувач має більше дописів, ніж це число, їх не можна буде видалити за один раз, і користувача також."
username_change_period: "Кількість днів після реєстрації, протягом яких новим обліковим записам можна змінювати своє ім'я користувача (0 щоб заборонити зміну імені користувача)."
email_editable: "Дозволити користувачам змінювати свою електронну скриньку після реєстрації."
default_digest_email_frequency: "Як часто користувачі отримують листи зі стислим викладом новин за замовчуванням. Вони можуть змінити це у своїх налаштуваннях."
default_external_links_in_new_tab: "Відкривати нові посилання у новій вкладці. Користувачі можуть змінити це у своїх налаштуваннях."
default_email_digest_frequency: "Як часто користувачі отримують листи зі стислим викладом новин за замовчуванням. Вони можуть змінити це у своїх налаштуваннях."
default_other_external_links_in_new_tab: "Відкривати нові посилання у новій вкладці. Користувачі можуть змінити це у своїх налаштуваннях."
allow_profile_backgrounds: "Дозволити користувачам завантажувати фони профілю."
enable_mobile_theme: "Мобільні пристрої використовуватимуть тему, дружню для них, з можливістю перемикатися на повний сайт. Відключіть це, якщо хочете використовувати власну, повністю чутливу, таблицю стилів."
display_name_on_posts: "Показувати повні імена користувачів на їх дописах у додаток до їх @username."

View File

@ -937,10 +937,10 @@ zh_CN:
automatically_download_gravatars: "为注册或更改邮箱的用户下载 Gravatar 头像。"
digest_topics: "邮件摘要中显示的最大主题数目。"
digest_min_excerpt_length: "在邮件摘要中每个帖子最少显示的字符数量。"
default_digest_email_frequency: "用户收到摘要邮件的默认间隔。用户可以在参数设置中更改这个设置。"
default_email_digest_frequency: "用户收到摘要邮件的默认间隔。用户可以在参数设置中更改这个设置。"
suppress_digest_email_after_days: "不发送摘要邮件给超过 (n) 天未出现的用户。"
disable_digest_emails: "为所有用户禁用摘要邮件。"
default_external_links_in_new_tab: "在新标签页中打开外部链接。用户可以在参数设置中更改这个设置。"
default_other_external_links_in_new_tab: "在新标签页中打开外部链接。用户可以在参数设置中更改这个设置。"
detect_custom_avatars: "检测用户是否上传了自定义个人头像。"
max_daily_gravatar_crawls: "一天内 Discourse 将自动检查 gravatar 自定义头像的次数"
public_user_custom_fields: "可公开显示的用户自定义属性白名单"

View File

@ -769,10 +769,10 @@ zh_TW:
automatically_download_gravatars: "當用戶註冊或更改EMail時下載 Gravatars 圖片"
digest_topics: "EMail 摘要中顯示的最大話題數量"
digest_min_excerpt_length: "EMail 摘要中每篇文章最少顯示的字元數量"
default_digest_email_frequency: "用戶收到摘要郵件的默認間隔。用戶可以在設定中更改。"
default_email_digest_frequency: "用戶收到摘要郵件的默認間隔。用戶可以在設定中更改。"
suppress_digest_email_after_days: "不發送摘要郵件給超過 (n) 天閒置的用戶。"
disable_digest_emails: "禁用發送摘要郵件給所有用戶。"
default_external_links_in_new_tab: "以新分頁開啟所有外部連結,用戶可於個人偏好設定更改設定。"
default_other_external_links_in_new_tab: "以新分頁開啟所有外部連結,用戶可於個人偏好設定更改設定。"
max_daily_gravatar_crawls: "一天內 Discourse 將自動檢查 Gravatar 自訂個人圖示的次數"
public_user_custom_fields: "用戶可設定公開顯示的自定欄位白名單。"
staff_user_custom_fields: "用戶可設定只給管理員顯示的自定欄位白名單。"

View File

@ -70,7 +70,6 @@ basic:
min: 0
limit_suggested_to_category:
default: false
default_external_links_in_new_tab: false
track_external_right_clicks:
client: true
default: false
@ -282,7 +281,6 @@ users:
default: ''
hidden: true
username_change_period: 3
auto_track_topics_after: 240000
email_editable: true
logout_redirect:
client: true
@ -474,9 +472,6 @@ email:
email_posts_context: 5
digest_min_excerpt_length: 100
digest_topics: 20
default_digest_email_frequency:
default: 7
enum: 'DigestEmailSiteSetting'
suppress_digest_email_after_days: 365
disable_digest_emails:
default: false
@ -841,7 +836,6 @@ uncategorized:
max_similar_results: 5
minimum_topics_similar: 50
new_topic_duration_minutes: 2880
previous_visit_timeout_hours: 1
staff_like_weight: 3
topic_view_duration_hours: 8
@ -959,3 +953,34 @@ uncategorized:
privacy_topic_id:
default: -1
hidden: true
user_preferences:
default_email_digest_frequency:
enum: 'DigestEmailSiteSetting'
default: 7
default_email_private_messages: true
default_email_direct: true
default_email_mailing_list_mode: false
default_email_always: false
default_other_new_topic_duration_minutes:
enum: 'NewTopicDurationSiteSetting'
default: 2880
default_other_auto_track_topics_after_msecs:
enum: 'AutoTrackDurationSiteSetting'
default: 240000
default_other_external_links_in_new_tab: false
default_other_enable_quoting: true
default_other_dynamic_favicon: false
default_other_disable_jump_reply: false
default_other_edit_history_public: false
default_categories_watching:
type: category_list
default: ''
default_categories_tracking:
type: category_list
default: ''
default_categories_muted:
type: category_list
default: ''

View File

@ -21,7 +21,7 @@ module SiteSettingExtension
end
def types
@types ||= Enum.new(:string, :time, :fixnum, :float, :bool, :null, :enum, :list, :url_list, :host_list)
@types ||= Enum.new(:string, :time, :fixnum, :float, :bool, :null, :enum, :list, :url_list, :host_list, :category_list)
end
def mutex

View File

@ -14,4 +14,13 @@ module SiteSettingValidations
validate_error :min_username_length_range if new_val < SiteSetting.min_username_length
validate_error :max_username_length_exists if User.where('length(username) > ?', new_val).exists?
end
def validate_default_categories(new_val)
validate_error :default_categories_already_selected if (new_val.split("|").to_set & SiteSetting.default_categories_selected).size > 0
end
alias_method :validate_default_categories_watching, :validate_default_categories
alias_method :validate_default_categories_tracking, :validate_default_categories
alias_method :validate_default_categories_muted, :validate_default_categories
end

View File

@ -64,7 +64,7 @@ describe SiteSettings::YamlLoader do
end
it "can load enum settings" do
receiver.expects(:setting).with('email', 'default_digest_email_frequency', 7, {enum: 'DigestEmailSiteSetting'})
receiver.expects(:setting).with('email', 'default_email_digest_frequency', 7, {enum: 'DigestEmailSiteSetting'})
receiver.load_yaml(enum)
end

View File

@ -1,4 +1,4 @@
email:
default_digest_email_frequency:
default_email_digest_frequency:
default: 7
enum: 'DigestEmailSiteSetting'

View File

@ -3,11 +3,11 @@ require_dependency 'jobs/base'
describe Jobs::EnqueueDigestEmails do
describe '#target_users' do
context 'disabled digests' do
let!(:user_no_digests) { Fabricate(:active_user, email_digests: false, last_emailed_at: 8.days.ago, last_seen_at: 10.days.ago) }
before { SiteSetting.stubs(:default_email_digest_frequency).returns("") }
let!(:user_no_digests) { Fabricate(:active_user, last_emailed_at: 8.days.ago, last_seen_at: 10.days.ago) }
it "doesn't return users with email disabled" do
expect(Jobs::EnqueueDigestEmails.new.target_user_ids.include?(user_no_digests.id)).to eq(false)

View File

@ -3,62 +3,69 @@ require "spec_helper"
describe Jobs::NotifyMailingListSubscribers do
context "with mailing list on" do
let(:user) { Fabricate(:user, mailing_list_mode: true) }
before { SiteSetting.stubs(:default_email_mailing_list_mode).returns(true) }
context "with a valid post" do
context "with mailing list on" do
let(:user) { Fabricate(:user) }
context "with a valid post" do
let!(:post) { Fabricate(:post, user: user) }
it "sends the email to the user" do
UserNotifications.expects(:mailing_list_notify).with(user, post).once
Jobs::NotifyMailingListSubscribers.new.execute(post_id: post.id)
end
end
context "with a deleted post" do
let!(:post) { Fabricate(:post, user: user, deleted_at: Time.now) }
it "doesn't send the email to the user" do
UserNotifications.expects(:mailing_list_notify).with(user, post).never
Jobs::NotifyMailingListSubscribers.new.execute(post_id: post.id)
end
end
context "with a user_deleted post" do
let!(:post) { Fabricate(:post, user: user, user_deleted: true) }
it "doesn't send the email to the user" do
UserNotifications.expects(:mailing_list_notify).with(user, post).never
Jobs::NotifyMailingListSubscribers.new.execute(post_id: post.id)
end
end
context "with a deleted topic" do
let!(:post) { Fabricate(:post, user: user) }
before do
post.topic.update_column(:deleted_at, Time.now)
end
it "doesn't send the email to the user" do
UserNotifications.expects(:mailing_list_notify).with(user, post).never
Jobs::NotifyMailingListSubscribers.new.execute(post_id: post.id)
end
end
end
context "to an anonymous user with mailing list on" do
let(:user) { Fabricate(:anonymous) }
let!(:post) { Fabricate(:post, user: user) }
it "sends the email to the user" do
UserNotifications.expects(:mailing_list_notify).with(user, post).once
Jobs::NotifyMailingListSubscribers.new.execute(post_id: post.id)
end
end
context "with a deleted post" do
let!(:post) { Fabricate(:post, user: user, deleted_at: Time.now) }
it "doesn't send the email to the user" do
UserNotifications.expects(:mailing_list_notify).with(user, post).never
Jobs::NotifyMailingListSubscribers.new.execute(post_id: post.id)
end
end
context "with a user_deleted post" do
let!(:post) { Fabricate(:post, user: user, user_deleted: true) }
it "doesn't send the email to the user" do
UserNotifications.expects(:mailing_list_notify).with(user, post).never
Jobs::NotifyMailingListSubscribers.new.execute(post_id: post.id)
end
end
context "with a deleted topic" do
let!(:post) { Fabricate(:post, user: user) }
before do
post.topic.update_column(:deleted_at, Time.now)
end
it "doesn't send the email to the user" do
UserNotifications.expects(:mailing_list_notify).with(user, post).never
Jobs::NotifyMailingListSubscribers.new.execute(post_id: post.id)
end
end
end
context "to an anonymous user with mailing list on" do
let(:user) { Fabricate(:anonymous, mailing_list_mode: true) }
let!(:post) { Fabricate(:post, user: user) }
it "doesn't send the email to the user" do
UserNotifications.expects(:mailing_list_notify).with(user, post).never
Jobs::NotifyMailingListSubscribers.new.execute(post_id: post.id)
end
end
context "with mailing list off" do
let(:user) { Fabricate(:user, mailing_list_mode: false) }
before { SiteSetting.stubs(:default_email_mailing_list_mode).returns(false) }
let(:user) { Fabricate(:user) }
let!(:post) { Fabricate(:post, user: user) }
it "doesn't send the email to the user" do

View File

@ -181,13 +181,13 @@ describe TopicUser do
it 'should automatically track topics after they are read for long enough' do
expect(topic_new_user.notification_level).to eq(TopicUser.notification_levels[:regular])
TopicUser.update_last_read(new_user, topic.id, 2, 1001)
TopicUser.update_last_read(new_user, topic.id, 2, SiteSetting.default_other_auto_track_topics_after_msecs + 1)
expect(TopicUser.get(topic, new_user).notification_level).to eq(TopicUser.notification_levels[:tracking])
end
it 'should not automatically track topics after they are read for long enough if changed manually' do
TopicUser.change(new_user, topic, notification_level: TopicUser.notification_levels[:regular])
TopicUser.update_last_read(new_user, topic, 2, 1001)
TopicUser.update_last_read(new_user, topic, 2, SiteSetting.default_other_auto_track_topics_after_msecs + 1)
expect(topic_new_user.notification_level).to eq(TopicUser.notification_levels[:regular])
end
end
@ -256,9 +256,13 @@ describe TopicUser do
it "will receive email notification for every topic" do
user1 = Fabricate(:user)
user2 = Fabricate(:user, mailing_list_mode: true)
SiteSetting.stubs(:default_email_mailing_list_mode).returns(true)
user2 = Fabricate(:user)
post = create_post
user3 = Fabricate(:user, mailing_list_mode: true)
user3 = Fabricate(:user)
create_post(topic_id: post.topic_id)
# mails posts from earlier topics

View File

@ -156,24 +156,6 @@ describe User do
expect(subject.email_direct).to eq(true)
end
context 'digest emails' do
it 'defaults to digests every week' do
expect(subject.email_digests).to eq(true)
expect(subject.digest_after_days).to eq(7)
end
it 'uses default_digest_email_frequency' do
SiteSetting.stubs(:default_digest_email_frequency).returns(1)
expect(subject.email_digests).to eq(true)
expect(subject.digest_after_days).to eq(1)
end
it 'disables digests by default if site setting says so' do
SiteSetting.stubs(:default_digest_email_frequency).returns('')
expect(subject.email_digests).to eq(false)
end
end
context 'after_save' do
before { subject.save }
@ -1223,4 +1205,50 @@ describe User do
end
end
context "when user preferences are overriden" do
before do
SiteSetting.stubs(:default_email_digest_frequency).returns(1) # daily
SiteSetting.stubs(:default_email_private_messages).returns(false)
SiteSetting.stubs(:default_email_direct).returns(false)
SiteSetting.stubs(:default_email_mailing_list_mode).returns(true)
SiteSetting.stubs(:default_email_always).returns(true)
SiteSetting.stubs(:default_other_new_topic_duration_minutes).returns(-1) # not viewed
SiteSetting.stubs(:default_other_auto_track_topics_after_msecs).returns(0) # immediately
SiteSetting.stubs(:default_other_external_links_in_new_tab).returns(true)
SiteSetting.stubs(:default_other_enable_quoting).returns(false)
SiteSetting.stubs(:default_other_dynamic_favicon).returns(true)
SiteSetting.stubs(:default_other_disable_jump_reply).returns(true)
SiteSetting.stubs(:default_other_edit_history_public).returns(true)
SiteSetting.stubs(:default_categories_watching).returns("1")
SiteSetting.stubs(:default_categories_tracking).returns("2")
SiteSetting.stubs(:default_categories_muted).returns("3")
end
it "has overriden preferences" do
user = Fabricate(:user)
expect(user.digest_after_days).to eq(1)
expect(user.email_private_messages).to eq(false)
expect(user.email_direct).to eq(false)
expect(user.mailing_list_mode).to eq(true)
expect(user.email_always).to eq(true)
expect(user.new_topic_duration_minutes).to eq(-1)
expect(user.auto_track_topics_after_msecs).to eq(0)
expect(user.external_links_in_new_tab).to eq(true)
expect(user.enable_quoting).to eq(false)
expect(user.dynamic_favicon).to eq(true)
expect(user.disable_jump_reply).to eq(true)
expect(user.edit_history_public).to eq(true)
expect(CategoryUser.lookup(user, :watching).pluck(:category_id)).to eq([1])
expect(CategoryUser.lookup(user, :tracking).pluck(:category_id)).to eq([2])
expect(CategoryUser.lookup(user, :muted).pluck(:category_id)).to eq([3])
end
end
end