Version bump
This commit is contained in:
commit
4f00241488
10
Gemfile.lock
10
Gemfile.lock
@ -140,7 +140,7 @@ GEM
|
||||
kgio (2.10.0)
|
||||
libv8 (5.3.332.38.3)
|
||||
listen (0.7.3)
|
||||
logster (1.2.5)
|
||||
logster (1.2.7)
|
||||
loofah (2.0.3)
|
||||
nokogiri (>= 1.5.9)
|
||||
lru_redux (1.1.0)
|
||||
@ -168,7 +168,7 @@ GEM
|
||||
netrc (0.11.0)
|
||||
nokogiri (1.6.8.1)
|
||||
mini_portile2 (~> 2.1.0)
|
||||
nokogumbo (1.4.7)
|
||||
nokogumbo (1.4.10)
|
||||
nokogiri
|
||||
oauth (0.5.1)
|
||||
oauth2 (1.0.0)
|
||||
@ -206,7 +206,7 @@ GEM
|
||||
omniauth-twitter (1.3.0)
|
||||
omniauth-oauth (~> 1.1)
|
||||
rack
|
||||
onebox (1.7.7)
|
||||
onebox (1.8.1)
|
||||
fast_blank (>= 1.0.0)
|
||||
htmlentities (~> 4.3.4)
|
||||
moneta (~> 0.8)
|
||||
@ -314,7 +314,7 @@ GEM
|
||||
ruby-readability (0.7.0)
|
||||
guess_html_encoding (>= 0.0.4)
|
||||
nokogiri (>= 1.6.0)
|
||||
sanitize (4.0.1)
|
||||
sanitize (4.4.0)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.4.4)
|
||||
nokogumbo (~> 1.4.1)
|
||||
@ -476,4 +476,4 @@ DEPENDENCIES
|
||||
unicorn
|
||||
|
||||
BUNDLED WITH
|
||||
1.13.7
|
||||
1.14.3
|
||||
|
||||
BIN
app/assets/images/favicons/pdf_48px.png
Normal file
BIN
app/assets/images/favicons/pdf_48px.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.1 KiB |
BIN
app/assets/images/favicons/pdf_64px.png
Normal file
BIN
app/assets/images/favicons/pdf_64px.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.8 KiB |
@ -1,16 +1,9 @@
|
||||
import computed from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
@computed('model.@each.enabled_setting')
|
||||
adminRoutes() {
|
||||
let routes = [];
|
||||
|
||||
this.get('model').forEach(p => {
|
||||
if (this.siteSettings[p.get('enabled_setting')] && p.get('admin_route')) {
|
||||
routes.push(p.get('admin_route'));
|
||||
adminRoutes: function() {
|
||||
return this.get('model').map(p => {
|
||||
if (p.get('enabled')) {
|
||||
return p.admin_route;
|
||||
}
|
||||
});
|
||||
|
||||
return routes;
|
||||
}
|
||||
}).compact();
|
||||
}.property()
|
||||
});
|
||||
|
||||
@ -11,11 +11,11 @@
|
||||
{{number report.yesterdayCount}} {{fa-icon "caret-up" class="up"}} {{fa-icon "caret-down" class="down"}}
|
||||
</td>
|
||||
|
||||
<td class="value {{report.sevenDayTrend}}" title={{number report.sevenDayCountTitle}}>
|
||||
<td class="value {{report.sevenDayTrend}}" title={{report.sevenDayCountTitle}}>
|
||||
{{number report.lastSevenDaysCount}} {{fa-icon "caret-up" class="up"}} {{fa-icon "caret-down" class="down"}}
|
||||
</td>
|
||||
|
||||
<td class="value {{report.thirtyDayTrend}}" title={{number report.thirtyDayCountTitle}}>
|
||||
<td class="value {{report.thirtyDayTrend}}" title={{report.thirtyDayCountTitle}}>
|
||||
{{number report.lastThirtyDaysCount}} {{fa-icon "caret-up" class="up"}} {{fa-icon "caret-down" class="down"}}
|
||||
</td>
|
||||
|
||||
|
||||
@ -33,6 +33,7 @@
|
||||
//= require ./discourse/models/permission-type
|
||||
//= require ./discourse/models/user-action-group
|
||||
//= require ./discourse/models/category
|
||||
//= require ./discourse/models/input-validation
|
||||
//= require ./discourse/lib/ajax-error
|
||||
//= require ./discourse/lib/search
|
||||
//= require ./discourse/lib/user-search
|
||||
|
||||
@ -54,6 +54,10 @@ export default Ember.Component.extend({
|
||||
if (!this.element || this.isDestroying || this.isDestroyed) { return; }
|
||||
|
||||
if (this.get('isAbsoluteUrl') && (this.get('composer.reply')||"").length === 0) {
|
||||
|
||||
// only feature links to external sites
|
||||
if (this.get('composer.title').match(new RegExp("^https?:\\/\\/" + window.location.hostname, "i"))) { return; }
|
||||
|
||||
// Try to onebox. If success, update post body and title.
|
||||
this.set('composer.loading', true);
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import Button from 'discourse/components/d-button';
|
||||
|
||||
export default Button.extend({
|
||||
label: 'topic.reply.topic.title',
|
||||
label: 'topic.reply.title',
|
||||
icon: 'reply',
|
||||
action: 'showLogin'
|
||||
});
|
||||
|
||||
@ -84,7 +84,7 @@ export default Ember.Component.extend(CleansUp, {
|
||||
_show(username, $target) {
|
||||
// No user card for anon
|
||||
if (this.siteSettings.hide_user_profiles_from_public && !this.currentUser) {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// XSS protection (should be encapsulated)
|
||||
|
||||
@ -44,7 +44,8 @@ export default TextField.extend({
|
||||
exclude: excludedUsernames(),
|
||||
includeGroups,
|
||||
allowedUsers,
|
||||
includeMentionableGroups
|
||||
includeMentionableGroups,
|
||||
group: self.get("group")
|
||||
});
|
||||
|
||||
return results;
|
||||
|
||||
@ -57,6 +57,7 @@ export default Ember.Controller.extend({
|
||||
application: Ember.inject.controller(),
|
||||
|
||||
replyAsNewTopicDraft: Em.computed.equal('model.draftKey', Composer.REPLY_AS_NEW_TOPIC_KEY),
|
||||
replyAsNewPrivateMessageDraft: Em.computed.equal('model.draftKey', Composer.REPLY_AS_NEW_PRIVATE_MESSAGE_KEY),
|
||||
checkedMessages: false,
|
||||
messageCount: null,
|
||||
showEditReason: false,
|
||||
@ -478,7 +479,7 @@ export default Ember.Controller.extend({
|
||||
}
|
||||
|
||||
// If user "created a new topic/post" or "replied as a new topic" successfully, remove the draft.
|
||||
if (result.responseJson.action === "create_post" || this.get('replyAsNewTopicDraft')) {
|
||||
if (result.responseJson.action === "create_post" || this.get('replyAsNewTopicDraft') || this.get('replyAsNewPrivateMessageDraft')) {
|
||||
this.destroyDraft();
|
||||
}
|
||||
if (this.get('model.action') === 'edit') {
|
||||
|
||||
@ -5,8 +5,9 @@ import { setting } from 'discourse/lib/computed';
|
||||
import { on } from 'ember-addons/ember-computed-decorators';
|
||||
import { emailValid } from 'discourse/lib/utilities';
|
||||
import InputValidation from 'discourse/models/input-validation';
|
||||
import PasswordValidation from "discourse/mixins/password-validation";
|
||||
|
||||
export default Ember.Controller.extend(ModalFunctionality, {
|
||||
export default Ember.Controller.extend(ModalFunctionality, PasswordValidation, {
|
||||
login: Ember.inject.controller(),
|
||||
|
||||
uniqueUsernameValidation: null,
|
||||
@ -16,7 +17,6 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
accountChallenge: 0,
|
||||
formSubmitted: false,
|
||||
rejectedEmails: Em.A([]),
|
||||
rejectedPasswords: Em.A([]),
|
||||
prefilledUsername: null,
|
||||
userFields: null,
|
||||
isDeveloper: false,
|
||||
@ -85,10 +85,6 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
});
|
||||
}.property(),
|
||||
|
||||
passwordInstructions: function() {
|
||||
return this.get('isDeveloper') ? I18n.t('user.password.instructions', {count: Discourse.SiteSettings.min_admin_password_length}) : I18n.t('user.password.instructions', {count: Discourse.SiteSettings.min_password_length});
|
||||
}.property('isDeveloper'),
|
||||
|
||||
nameInstructions: function() {
|
||||
return I18n.t(Discourse.SiteSettings.full_name_required ? 'user.name.instructions_required' : 'user.name.instructions');
|
||||
}.property(),
|
||||
@ -293,55 +289,6 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
return( this.get('globalNicknameExists') || false );
|
||||
},
|
||||
|
||||
// Validate the password
|
||||
passwordValidation: function() {
|
||||
if (!this.get('passwordRequired')) {
|
||||
return InputValidation.create({ ok: true });
|
||||
}
|
||||
|
||||
// If blank, fail without a reason
|
||||
const password = this.get("accountPassword");
|
||||
if (Ember.isEmpty(this.get('accountPassword'))) {
|
||||
return InputValidation.create({ failed: true });
|
||||
}
|
||||
|
||||
// If too short
|
||||
const passwordLength = this.get('isDeveloper') ? Discourse.SiteSettings.min_admin_password_length : Discourse.SiteSettings.min_password_length;
|
||||
if (password.length < passwordLength) {
|
||||
return InputValidation.create({
|
||||
failed: true,
|
||||
reason: I18n.t('user.password.too_short')
|
||||
});
|
||||
}
|
||||
|
||||
if (this.get('rejectedPasswords').includes(password)) {
|
||||
return InputValidation.create({
|
||||
failed: true,
|
||||
reason: I18n.t('user.password.common')
|
||||
});
|
||||
}
|
||||
|
||||
if (!Ember.isEmpty(this.get('accountUsername')) && this.get('accountPassword') === this.get('accountUsername')) {
|
||||
return InputValidation.create({
|
||||
failed: true,
|
||||
reason: I18n.t('user.password.same_as_username')
|
||||
});
|
||||
}
|
||||
|
||||
if (!Ember.isEmpty(this.get('accountEmail')) && this.get('accountPassword') === this.get('accountEmail')) {
|
||||
return InputValidation.create({
|
||||
failed: true,
|
||||
reason: I18n.t('user.password.same_as_email')
|
||||
});
|
||||
}
|
||||
|
||||
// Looks good!
|
||||
return InputValidation.create({
|
||||
ok: true,
|
||||
reason: I18n.t('user.password.ok')
|
||||
});
|
||||
}.property('accountPassword', 'rejectedPasswords.[]', 'accountUsername', 'accountEmail', 'isDeveloper'),
|
||||
|
||||
@on('init')
|
||||
fetchConfirmationValue() {
|
||||
return ajax('/users/hp.json').then(json => {
|
||||
|
||||
@ -2,6 +2,7 @@ import ModalFunctionality from 'discourse/mixins/modal-functionality';
|
||||
import { categoryBadgeHTML } from 'discourse/helpers/category-link';
|
||||
import computed from 'ember-addons/ember-computed-decorators';
|
||||
import { propertyGreaterThan, propertyLessThan } from 'discourse/lib/computed';
|
||||
import { on } from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
function customTagArray(fieldName) {
|
||||
return function() {
|
||||
@ -17,9 +18,10 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
loading: true,
|
||||
viewMode: "side_by_side",
|
||||
|
||||
_changeViewModeOnMobile: function() {
|
||||
if (this.site.mobileView) { this.set("viewMode", "inline"); }
|
||||
}.on("init"),
|
||||
@on('init')
|
||||
_changeViewModeOnMobile() {
|
||||
if (this.site && this.site.mobileView) { this.set("viewMode", "inline"); }
|
||||
},
|
||||
|
||||
previousFeaturedLink: Em.computed.alias('model.featured_link_changes.previous'),
|
||||
currentFeaturedLink: Em.computed.alias('model.featured_link_changes.current'),
|
||||
@ -109,9 +111,14 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
return !prevHidden && this.currentUser && this.currentUser.get('staff');
|
||||
},
|
||||
|
||||
@computed("model.wiki", "model.last_revision", "model.current_revision")
|
||||
displayEdit(wiki, lastRevision, currentRevision) {
|
||||
return wiki && (lastRevision === currentRevision);
|
||||
@computed("model.last_revision", "model.current_revision", "model.can_edit")
|
||||
displayEdit(lastRevision, currentRevision, canEdit) {
|
||||
return canEdit && (lastRevision === currentRevision);
|
||||
},
|
||||
|
||||
@computed("model.wiki")
|
||||
editButtonLabel(wiki) {
|
||||
return `post.revisions.controls.${wiki ? 'edit_wiki' : 'edit_post'}`;
|
||||
},
|
||||
|
||||
@computed()
|
||||
@ -192,7 +199,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
hideVersion() { this.hide(this.get("model.post_id"), this.get("model.current_revision")); },
|
||||
showVersion() { this.show(this.get("model.post_id"), this.get("model.current_revision")); },
|
||||
|
||||
editWiki() {
|
||||
editPost() {
|
||||
this.get('topicController').send('editPost', this.get('post'));
|
||||
this.send('closeModal');
|
||||
},
|
||||
|
||||
@ -27,19 +27,22 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
return Discourse.User.currentProp("admin");
|
||||
}.property(),
|
||||
|
||||
disabled: function() {
|
||||
if (this.get('model.saving')) return true;
|
||||
if (Ember.isEmpty(this.get('emailOrUsername'))) return true;
|
||||
const emailOrUsername = this.get('emailOrUsername').trim();
|
||||
@computed('isAdmin', 'emailOrUsername', 'invitingToTopic', 'isPrivateTopic', 'model.groupNames', 'model.saving', 'model.details.can_invite_to')
|
||||
disabled(isAdmin, emailOrUsername, invitingToTopic, isPrivateTopic, groupNames, saving, can_invite_to) {
|
||||
if (saving) return true;
|
||||
if (Ember.isEmpty(emailOrUsername)) return true;
|
||||
const emailTrimmed = emailOrUsername.trim();
|
||||
|
||||
// when inviting to forum, email must be valid
|
||||
if (!this.get('invitingToTopic') && !emailValid(emailOrUsername)) return true;
|
||||
if (!invitingToTopic && !emailValid(emailTrimmed)) return true;
|
||||
// normal users (not admin) can't invite users to private topic via email
|
||||
if (!this.get('isAdmin') && this.get('isPrivateTopic') && emailValid(emailOrUsername)) return true;
|
||||
if (!isAdmin && isPrivateTopic && emailValid(emailTrimmed)) return true;
|
||||
// when inviting to private topic via email, group name must be specified
|
||||
if (this.get('isPrivateTopic') && Ember.isEmpty(this.get('model.groupNames')) && emailValid(emailOrUsername)) return true;
|
||||
if (this.get('model.details.can_invite_to')) return false;
|
||||
if (isPrivateTopic && Ember.isEmpty(groupNames) && emailValid(emailTrimmed)) return true;
|
||||
|
||||
if (can_invite_to) return false;
|
||||
return false;
|
||||
}.property('isAdmin', 'emailOrUsername', 'invitingToTopic', 'isPrivateTopic', 'model.groupNames', 'model.saving'),
|
||||
},
|
||||
|
||||
disabledCopyLink: function() {
|
||||
if (this.get('hasCustomMessage')) return true;
|
||||
@ -65,9 +68,17 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
return this.get('model') !== this.currentUser;
|
||||
}.property('model'),
|
||||
|
||||
showCopyInviteButton: function() {
|
||||
return (!Discourse.SiteSettings.enable_sso && !this.get('isMessage'));
|
||||
}.property('isMessage'),
|
||||
@computed('model', 'model.details.can_invite_via_email')
|
||||
canInviteViaEmail(model, can_invite_via_email) {
|
||||
return (this.get('model') === this.currentUser) ?
|
||||
true :
|
||||
can_invite_via_email;
|
||||
},
|
||||
|
||||
@computed('isMessage', 'canInviteViaEmail')
|
||||
showCopyInviteButton(isMessage, canInviteViaEmail) {
|
||||
return (canInviteViaEmail && !isMessage);
|
||||
},
|
||||
|
||||
topicId: Ember.computed.alias('model.id'),
|
||||
|
||||
@ -83,32 +94,38 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
}.property('invitingToTopic'),
|
||||
|
||||
// Show Groups? (add invited user to private group)
|
||||
showGroups: function() {
|
||||
return this.get('isAdmin') && (emailValid(this.get('emailOrUsername')) || this.get('isPrivateTopic') || !this.get('invitingToTopic')) && !Discourse.SiteSettings.enable_sso && Discourse.SiteSettings.enable_local_logins && !this.get('isMessage');
|
||||
}.property('isAdmin', 'emailOrUsername', 'isPrivateTopic', 'isMessage', 'invitingToTopic'),
|
||||
@computed('isAdmin', 'emailOrUsername', 'isPrivateTopic', 'isMessage', 'invitingToTopic', 'canInviteViaEmail')
|
||||
showGroups(isAdmin, emailOrUsername, isPrivateTopic, isMessage, invitingToTopic, canInviteViaEmail) {
|
||||
return isAdmin &&
|
||||
canInviteViaEmail &&
|
||||
!isMessage &&
|
||||
(emailValid(emailOrUsername) || isPrivateTopic || !invitingToTopic);
|
||||
},
|
||||
|
||||
showCustomMessage: function() {
|
||||
return (this.get('model') === this.currentUser || emailValid(this.get('emailOrUsername')));
|
||||
}.property('emailOrUsername'),
|
||||
@computed('emailOrUsername')
|
||||
showCustomMessage(emailOrUsername) {
|
||||
return (this.get('model') === this.currentUser || emailValid(emailOrUsername));
|
||||
},
|
||||
|
||||
// Instructional text for the modal.
|
||||
inviteInstructions: function() {
|
||||
if (Discourse.SiteSettings.enable_sso || !Discourse.SiteSettings.enable_local_logins) {
|
||||
// inviting existing user when SSO enabled
|
||||
@computed('isMessage', 'invitingToTopic', 'emailOrUsername', 'isPrivateTopic', 'isAdmin', 'canInviteViaEmail')
|
||||
inviteInstructions(isMessage, invitingToTopic, emailOrUsername, isPrivateTopic, isAdmin, canInviteViaEmail) {
|
||||
if (!canInviteViaEmail) {
|
||||
// can't invite via email, only existing users
|
||||
return I18n.t('topic.invite_reply.sso_enabled');
|
||||
} else if (this.get('isMessage')) {
|
||||
} else if (isMessage) {
|
||||
// inviting to a message
|
||||
return I18n.t('topic.invite_private.email_or_username');
|
||||
} else if (this.get('invitingToTopic')) {
|
||||
} else if (invitingToTopic) {
|
||||
// inviting to a private/public topic
|
||||
if (this.get('isPrivateTopic') && !this.get('isAdmin')) {
|
||||
if (isPrivateTopic && !isAdmin) {
|
||||
// inviting to a private topic and is not admin
|
||||
return I18n.t('topic.invite_reply.to_username');
|
||||
} else {
|
||||
// when inviting to a topic, display instructions based on provided entity
|
||||
if (Ember.isEmpty(this.get('emailOrUsername'))) {
|
||||
if (Ember.isEmpty(emailOrUsername)) {
|
||||
return I18n.t('topic.invite_reply.to_topic_blank');
|
||||
} else if (emailValid(this.get('emailOrUsername'))) {
|
||||
} else if (emailValid(emailOrUsername)) {
|
||||
this.set("inviteIcon", "envelope");
|
||||
return I18n.t('topic.invite_reply.to_topic_email');
|
||||
} else {
|
||||
@ -120,7 +137,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
// inviting to forum
|
||||
return I18n.t('topic.invite_reply.to_forum');
|
||||
}
|
||||
}.property('isMessage', 'invitingToTopic', 'emailOrUsername'),
|
||||
},
|
||||
|
||||
showGroupsClass: function() {
|
||||
return this.get('isPrivateTopic') ? 'required' : 'optional';
|
||||
@ -147,11 +164,12 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||
return this.get('isMessage') ? I18n.t('topic.invite_private.error') : I18n.t('topic.invite_reply.error');
|
||||
}.property('isMessage'),
|
||||
|
||||
placeholderKey: function() {
|
||||
return (Discourse.SiteSettings.enable_sso || !Discourse.SiteSettings.enable_local_logins) ?
|
||||
'topic.invite_reply.username_placeholder' :
|
||||
'topic.invite_private.email_or_username_placeholder';
|
||||
}.property(),
|
||||
@computed('canInviteViaEmail')
|
||||
placeholderKey(canInviteViaEmail) {
|
||||
return (canInviteViaEmail) ?
|
||||
'topic.invite_private.email_or_username_placeholder' :
|
||||
'topic.invite_reply.username_placeholder';
|
||||
},
|
||||
|
||||
customMessagePlaceholder: function() {
|
||||
return I18n.t('invite.custom_message_placeholder');
|
||||
|
||||
@ -0,0 +1,64 @@
|
||||
import { default as computed } from 'ember-addons/ember-computed-decorators';
|
||||
import getUrl from 'discourse-common/lib/get-url';
|
||||
import DiscourseURL from 'discourse/lib/url';
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
import PasswordValidation from "discourse/mixins/password-validation";
|
||||
|
||||
export default Ember.Controller.extend(PasswordValidation, {
|
||||
isDeveloper: Ember.computed.alias('model.is_developer'),
|
||||
passwordRequired: true,
|
||||
errorMessage: null,
|
||||
successMessage: null,
|
||||
requiresApproval: false,
|
||||
redirected: false,
|
||||
|
||||
@computed()
|
||||
continueButtonText() {
|
||||
return I18n.t('password_reset.continue', {site_name: this.siteSettings.title});
|
||||
},
|
||||
|
||||
@computed('redirectTo')
|
||||
redirectHref(redirectTo) {
|
||||
return Discourse.getURL(redirectTo || '/');
|
||||
},
|
||||
|
||||
lockImageUrl: getUrl('/images/lock.svg'),
|
||||
|
||||
actions: {
|
||||
submit() {
|
||||
ajax({
|
||||
url: `/users/password-reset/${this.get('model.token')}.json`,
|
||||
type: 'PUT',
|
||||
data: {
|
||||
password: this.get('accountPassword')
|
||||
}
|
||||
}).then(result => {
|
||||
if (result.success) {
|
||||
this.set('successMessage', result.message);
|
||||
this.set('redirectTo', result.redirect_to);
|
||||
if (result.requires_approval) {
|
||||
this.set('requiresApproval', true);
|
||||
} else {
|
||||
this.set('redirected', true);
|
||||
DiscourseURL.redirectTo(result.redirect_to || '/');
|
||||
}
|
||||
} else {
|
||||
if (result.errors && result.errors.password && result.errors.password.length > 0) {
|
||||
this.get('rejectedPasswords').pushObject(this.get('accountPassword'));
|
||||
this.get('rejectedPasswordsMessages').set(this.get('accountPassword'), result.errors.password[0]);
|
||||
}
|
||||
if (result.message) {
|
||||
this.set('errorMessage', result.message);
|
||||
}
|
||||
}
|
||||
}).catch(response => {
|
||||
throw response;
|
||||
});
|
||||
},
|
||||
|
||||
done() {
|
||||
this.set('redirected', true);
|
||||
DiscourseURL.redirectTo(this.get('redirectTo') || '/');
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -656,11 +656,31 @@ export default Ember.Controller.extend(SelectedPostsCount, BufferedContent, {
|
||||
const quotedText = Quote.build(post, quoteState.buffer);
|
||||
quoteState.clear();
|
||||
|
||||
composerController.open({
|
||||
action: Composer.CREATE_TOPIC,
|
||||
draftKey: Composer.REPLY_AS_NEW_TOPIC_KEY,
|
||||
categoryId: this.get('model.category.id')
|
||||
}).then(() => {
|
||||
var options;
|
||||
if (this.get('model.isPrivateMessage')) {
|
||||
let users = this.get('model.details.allowed_users');
|
||||
let groups = this.get('model.details.allowed_groups');
|
||||
|
||||
let usernames = [];
|
||||
users.forEach(user => usernames.push(user.username));
|
||||
groups.forEach(group => usernames.push(group.name));
|
||||
usernames = usernames.join();
|
||||
|
||||
options = {
|
||||
action: Composer.PRIVATE_MESSAGE,
|
||||
archetypeId: 'private_message',
|
||||
draftKey: Composer.REPLY_AS_NEW_PRIVATE_MESSAGE_KEY,
|
||||
usernames: usernames
|
||||
};
|
||||
} else {
|
||||
options = {
|
||||
action: Composer.CREATE_TOPIC,
|
||||
draftKey: Composer.REPLY_AS_NEW_TOPIC_KEY,
|
||||
categoryId: this.get('model.category.id')
|
||||
};
|
||||
}
|
||||
|
||||
composerController.open(options).then(() => {
|
||||
return Em.isEmpty(quotedText) ? "" : quotedText;
|
||||
}).then(q => {
|
||||
const postUrl = `${location.protocol}//${location.host}${post.get('url')}`;
|
||||
|
||||
@ -13,7 +13,7 @@ registerUnbound('number', (orig, params) => {
|
||||
|
||||
let title = I18n.toNumber(orig, { precision: 0 });
|
||||
if (params.numberKey) {
|
||||
title = I18n.t(params.numberKey, { number: title, count: parseInt(title) });
|
||||
title = I18n.t(params.numberKey, { number: title, count: parseInt(orig) });
|
||||
}
|
||||
|
||||
let classNames = 'number';
|
||||
|
||||
@ -5,13 +5,17 @@ import { addButton } from 'discourse/widgets/post-menu';
|
||||
import { includeAttributes } from 'discourse/lib/transform-post';
|
||||
import { addToolbarCallback } from 'discourse/components/d-editor';
|
||||
import { addWidgetCleanCallback } from 'discourse/components/mount-widget';
|
||||
import { createWidget, decorateWidget, changeSetting } from 'discourse/widgets/widget';
|
||||
import { createWidget, reopenWidget, decorateWidget, changeSetting } from 'discourse/widgets/widget';
|
||||
import { onPageChange } from 'discourse/lib/page-tracker';
|
||||
import { preventCloak } from 'discourse/widgets/post-stream';
|
||||
import { h } from 'virtual-dom';
|
||||
import { addFlagProperty } from 'discourse/components/site-header';
|
||||
import { addPopupMenuOptionsCallback } from 'discourse/controllers/composer';
|
||||
import { extraConnectorClass } from 'discourse/lib/plugin-connectors';
|
||||
import { addPostSmallActionIcon } from 'discourse/widgets/post-small-action';
|
||||
|
||||
// If you add any methods to the API ensure you bump up this number
|
||||
const PLUGIN_API_VERSION = 0.8;
|
||||
|
||||
class PluginApi {
|
||||
constructor(version, container) {
|
||||
@ -307,6 +311,16 @@ class PluginApi {
|
||||
return createWidget(name, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exposes the widget update ability to plugins. Updates the widget
|
||||
* registry for the given widget name to include the properties on args
|
||||
* See `reopenWidget` in `discourse/widgets/widget` from more ifo.
|
||||
**/
|
||||
|
||||
reopenWidget(name, args) {
|
||||
return reopenWidget(name, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a property that can be summed for calculating the flag counter
|
||||
**/
|
||||
@ -352,12 +366,23 @@ class PluginApi {
|
||||
registerConnectorClass(outletName, connectorName, klass) {
|
||||
extraConnectorClass(`${outletName}/${connectorName}`, klass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a small icon to be used for custom small post actions
|
||||
*
|
||||
* ```javascript
|
||||
* api.registerPostSmallActionIcon('assign-to', 'user-add');
|
||||
* ```
|
||||
**/
|
||||
addPostSmallActionIcon(key, icon) {
|
||||
addPostSmallActionIcon(key, icon);
|
||||
}
|
||||
}
|
||||
|
||||
let _pluginv01;
|
||||
function getPluginApi(version) {
|
||||
version = parseFloat(version);
|
||||
if (version <= 0.6) {
|
||||
if (version <= PLUGIN_API_VERSION) {
|
||||
if (!_pluginv01) {
|
||||
_pluginv01 = new PluginApi(version, Discourse.__container__);
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ var cache = {},
|
||||
currentTerm,
|
||||
oldSearch;
|
||||
|
||||
function performSearch(term, topicId, includeGroups, includeMentionableGroups, allowedUsers, resultsFn) {
|
||||
function performSearch(term, topicId, includeGroups, includeMentionableGroups, allowedUsers, group, resultsFn) {
|
||||
var cached = cache[term];
|
||||
if (cached) {
|
||||
resultsFn(cached);
|
||||
@ -19,6 +19,7 @@ function performSearch(term, topicId, includeGroups, includeMentionableGroups, a
|
||||
topic_id: topicId,
|
||||
include_groups: includeGroups,
|
||||
include_mentionable_groups: includeMentionableGroups,
|
||||
group: group,
|
||||
topic_allowed_users: allowedUsers }
|
||||
});
|
||||
|
||||
@ -79,7 +80,8 @@ export default function userSearch(options) {
|
||||
includeGroups = options.includeGroups,
|
||||
includeMentionableGroups = options.includeMentionableGroups,
|
||||
allowedUsers = options.allowedUsers,
|
||||
topicId = options.topicId;
|
||||
topicId = options.topicId,
|
||||
group = options.group;
|
||||
|
||||
|
||||
if (oldSearch) {
|
||||
@ -105,10 +107,16 @@ export default function userSearch(options) {
|
||||
resolve(CANCELLED_STATUS);
|
||||
}, 5000);
|
||||
|
||||
debouncedSearch(term, topicId, includeGroups, includeMentionableGroups, allowedUsers, function(r) {
|
||||
clearTimeout(clearPromise);
|
||||
resolve(organizeResults(r, options));
|
||||
});
|
||||
debouncedSearch(term,
|
||||
topicId,
|
||||
includeGroups,
|
||||
includeMentionableGroups,
|
||||
allowedUsers,
|
||||
group,
|
||||
function(r) {
|
||||
clearTimeout(clearPromise);
|
||||
resolve(organizeResults(r, options));
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@ -170,7 +170,7 @@ export function validateUploadedFiles(files, opts) {
|
||||
|
||||
// CHROME ONLY: if the image was pasted, sets its name to a default one
|
||||
if (typeof Blob !== "undefined" && typeof File !== "undefined") {
|
||||
if (upload instanceof Blob && !(upload instanceof File) && upload.type === "image/png") { upload.name = "blob.png"; }
|
||||
if (upload instanceof Blob && !(upload instanceof File) && upload.type === "image/png") { upload.name = "image.png"; }
|
||||
}
|
||||
|
||||
opts = opts || {};
|
||||
|
||||
@ -0,0 +1,71 @@
|
||||
import InputValidation from 'discourse/models/input-validation';
|
||||
import { default as computed } from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
export default Ember.Mixin.create({
|
||||
|
||||
rejectedPasswords: null,
|
||||
|
||||
init() {
|
||||
this._super();
|
||||
this.set('rejectedPasswords', []);
|
||||
this.set('rejectedPasswordsMessages', Ember.Map.create());
|
||||
},
|
||||
|
||||
@computed('passwordMinLength')
|
||||
passwordInstructions() {
|
||||
return I18n.t('user.password.instructions', {count: this.get('passwordMinLength')});
|
||||
},
|
||||
|
||||
@computed('isDeveloper')
|
||||
passwordMinLength() {
|
||||
return this.get('isDeveloper') ? this.siteSettings.min_admin_password_length : this.siteSettings.min_password_length;
|
||||
},
|
||||
|
||||
@computed('accountPassword', 'passwordRequired', 'rejectedPasswords.[]', 'accountUsername', 'accountEmail', 'isDeveloper')
|
||||
passwordValidation(password, passwordRequired, rejectedPasswords, accountUsername, accountEmail, isDeveloper) {
|
||||
if (!passwordRequired) {
|
||||
return InputValidation.create({ ok: true });
|
||||
}
|
||||
|
||||
if (rejectedPasswords.includes(password)) {
|
||||
return InputValidation.create({
|
||||
failed: true,
|
||||
reason: this.get('rejectedPasswordsMessages').get(password) || I18n.t('user.password.common')
|
||||
});
|
||||
}
|
||||
|
||||
// If blank, fail without a reason
|
||||
if (Ember.isEmpty(password)) {
|
||||
return InputValidation.create({ failed: true });
|
||||
}
|
||||
|
||||
// If too short
|
||||
const passwordLength = isDeveloper ? this.siteSettings.min_admin_password_length : this.siteSettings.min_password_length;
|
||||
if (password.length < passwordLength) {
|
||||
return InputValidation.create({
|
||||
failed: true,
|
||||
reason: I18n.t('user.password.too_short')
|
||||
});
|
||||
}
|
||||
|
||||
if (!Ember.isEmpty(accountUsername) && password === accountUsername) {
|
||||
return InputValidation.create({
|
||||
failed: true,
|
||||
reason: I18n.t('user.password.same_as_username')
|
||||
});
|
||||
}
|
||||
|
||||
if (!Ember.isEmpty(accountEmail) && password === accountEmail) {
|
||||
return InputValidation.create({
|
||||
failed: true,
|
||||
reason: I18n.t('user.password.same_as_email')
|
||||
});
|
||||
}
|
||||
|
||||
// Looks good!
|
||||
return InputValidation.create({
|
||||
ok: true,
|
||||
reason: I18n.t('user.password.ok')
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -18,6 +18,7 @@ const CLOSED = 'closed',
|
||||
REPLY = 'reply',
|
||||
EDIT = 'edit',
|
||||
REPLY_AS_NEW_TOPIC_KEY = "reply_as_new_topic",
|
||||
REPLY_AS_NEW_PRIVATE_MESSAGE_KEY = "reply_as_new_private_message",
|
||||
|
||||
// When creating, these fields are moved into the post model from the composer model
|
||||
_create_serializer = {
|
||||
@ -814,7 +815,8 @@ Composer.reopenClass({
|
||||
EDIT,
|
||||
|
||||
// Draft key
|
||||
REPLY_AS_NEW_TOPIC_KEY
|
||||
REPLY_AS_NEW_TOPIC_KEY,
|
||||
REPLY_AS_NEW_PRIVATE_MESSAGE_KEY
|
||||
});
|
||||
|
||||
export default Composer;
|
||||
|
||||
@ -63,6 +63,7 @@ export default function() {
|
||||
|
||||
// User routes
|
||||
this.route('users', { resetNamespace: true });
|
||||
this.route('password-reset', { path: '/users/password-reset/:token' });
|
||||
this.route('user', { path: '/users/:username', resetNamespace: true }, function() {
|
||||
this.route('summary');
|
||||
this.route('userActivity', { path: '/activity', resetNamespace: true }, function() {
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
import PreloadStore from 'preload-store';
|
||||
import { ajax } from 'discourse/lib/ajax';
|
||||
|
||||
export default Discourse.Route.extend({
|
||||
titleToken() {
|
||||
return I18n.t('login.reset_password');
|
||||
},
|
||||
|
||||
model(params) {
|
||||
if (PreloadStore.get("password_reset")) {
|
||||
return PreloadStore.getAndRemove("password_reset").then(json => _.merge(params, json));
|
||||
}
|
||||
},
|
||||
|
||||
afterModel(model) {
|
||||
// confirm token here so email clients who crawl URLs don't invalidate the link
|
||||
if (model) {
|
||||
return ajax({ url: `/users/confirm-email-token/${model.token}.json`, dataType: 'json' });
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -15,7 +15,11 @@
|
||||
|
||||
{{#if topic.details.can_reply_as_new_topic}}
|
||||
<div class='reply-as-new-topic'>
|
||||
<a href {{action "replyAsNewTopic"}} aria-label={{i18n 'post.reply_as_new_topic'}} title={{i18n 'post.reply_as_new_topic'}}>{{fa-icon "plus"}}{{i18n 'topic.create'}}</a>
|
||||
{{#if topic.isPrivateMessage}}
|
||||
<a href {{action "replyAsNewTopic"}} aria-label={{i18n 'post.reply_as_new_private_message'}} title={{i18n 'post.reply_as_new_private_message'}}>{{fa-icon "plus"}}{{i18n 'user.new_private_message'}}</a>
|
||||
{{else}}
|
||||
<a href {{action "replyAsNewTopic"}} aria-label={{i18n 'post.reply_as_new_topic'}} title={{i18n 'post.reply_as_new_topic'}}>{{fa-icon "plus"}}{{i18n 'topic.create'}}</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
|
||||
@ -68,8 +68,8 @@
|
||||
{{d-button class="btn-primary create"
|
||||
icon="reply"
|
||||
action=replyToPost
|
||||
label="topic.reply.topic.title"
|
||||
title="topic.reply.topic.help"}}
|
||||
label="topic.reply.title"
|
||||
title="topic.reply.help"}}
|
||||
{{/if}}
|
||||
|
||||
{{plugin-outlet name="after-topic-footer-main-buttons"
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{{#d-modal-body title="history" maxHeight="80%"}}
|
||||
<div>
|
||||
<div id="revision">
|
||||
<div id="revision-controls">
|
||||
{{d-button action="loadFirstVersion" icon="fast-backward" title="post.revisions.controls.first" disabled=loadFirstDisabled}}
|
||||
{{d-button action="loadPreviousVersion" icon="backward" title="post.revisions.controls.previous" disabled=loadPreviousDisabled}}
|
||||
@ -12,6 +12,12 @@
|
||||
{{d-button action="loadLastVersion" icon="fast-forward" title="post.revisions.controls.last" disabled=loadLastDisabled}}
|
||||
</div>
|
||||
|
||||
{{#if displayEdit}}
|
||||
{{d-button action="editPost"
|
||||
icon="pencil"
|
||||
label=editButtonLabel}}
|
||||
{{/if}}
|
||||
|
||||
<div id="display-modes">
|
||||
{{d-button action="displayInline"
|
||||
icon="square-o"
|
||||
@ -114,6 +120,8 @@
|
||||
{{{bodyDiff}}}
|
||||
{{/links-redirect}}
|
||||
|
||||
<hr>
|
||||
|
||||
{{#if displayRevert}}
|
||||
{{d-button action="revertToVersion" icon="undo" label="post.revisions.controls.revert" class="btn-danger" disabled=loading}}
|
||||
{{/if}}
|
||||
@ -127,9 +135,9 @@
|
||||
{{/if}}
|
||||
|
||||
{{#if displayEdit}}
|
||||
{{d-button action="editWiki"
|
||||
{{d-button action="editPost"
|
||||
icon="pencil"
|
||||
label="post.revisions.controls.edit_wiki"}}
|
||||
label=editButtonLabel}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/d-modal-body}}
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
<div class="container password-reset clearfix">
|
||||
<div class="pull-left col-image">
|
||||
<img src={{lockImageUrl}} class="password-reset-img">
|
||||
</div>
|
||||
|
||||
<div class="pull-left col-form">
|
||||
{{#if successMessage}}
|
||||
<p>{{successMessage}}</p>
|
||||
|
||||
{{#if requiresApproval}}
|
||||
<p>{{i18n 'login.not_approved'}}</p>
|
||||
{{else}}
|
||||
{{#unless redirected}}
|
||||
<a class="btn" href="{{redirectHref}}" {{action "done"}}>{{continueButtonText}}</a>
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<form>
|
||||
|
||||
<h2>{{i18n 'user.change_password.choose'}}</h2>
|
||||
|
||||
<div class="input">
|
||||
{{password-field value=accountPassword type="password" id="new-account-password" capsLockOn=capsLockOn autofocus="autofocus"}}
|
||||
{{input-tip validation=passwordValidation}}
|
||||
</div>
|
||||
|
||||
<div class="instructions">
|
||||
<div class="caps-lock-warning {{unless capsLockOn 'invisible'}}"><i class="fa fa-exclamation-triangle"></i> {{i18n 'login.caps_lock_warning'}}</div>
|
||||
</div>
|
||||
|
||||
<button class='btn btn-primary' {{action "submit"}}>{{i18n 'user.change_password.set_password'}}</button>
|
||||
|
||||
{{#if errorMessage}}
|
||||
<br/><br/>
|
||||
<div class='alert alert-error'>{{errorMessage}}</div>
|
||||
{{/if}}
|
||||
|
||||
</form>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
@ -200,7 +200,9 @@
|
||||
replyToPost=(action "replyToPost")
|
||||
}}
|
||||
{{else}}
|
||||
{{d-button icon="reply" class="btn-primary" action="showLogin" label="topic.reply.topic.title"}}
|
||||
<div id="topic-footer-button">
|
||||
{{d-button icon="reply" class="btn-primary pull-right" action="showLogin" label="topic.reply.title"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
|
||||
@ -148,7 +148,7 @@
|
||||
<dt class="groups">{{i18n 'groups.title' count=model.displayGroups.length}}</dt>
|
||||
<dd class='groups'>
|
||||
{{#each model.displayGroups as |group|}}
|
||||
<span>{{#link-to 'group' group class="group-link"}}{{group.name}}{{/link-to}}</span>
|
||||
<span>{{#link-to 'group' group.name class="group-link"}}{{group.name}}{{/link-to}}</span>
|
||||
{{/each}}
|
||||
</dd>
|
||||
{{/if}}
|
||||
|
||||
@ -4,7 +4,11 @@ import { h } from 'virtual-dom';
|
||||
createWidget('menu-links', {
|
||||
html(attrs) {
|
||||
const links = [].concat(attrs.contents());
|
||||
const liOpts = { className: attrs.heading ? 'heading' : '' };
|
||||
const liOpts = {};
|
||||
|
||||
if (attrs.heading) {
|
||||
liOpts.className = 'header';
|
||||
}
|
||||
|
||||
const result = [];
|
||||
result.push(h('ul.menu-links.columned', links.map(l => h('li', liOpts, l))));
|
||||
|
||||
@ -135,7 +135,7 @@ registerButton('reply', attrs => {
|
||||
if (!attrs.canCreatePost) { return; }
|
||||
|
||||
if (!attrs.mobileView) {
|
||||
args.label = 'topic.reply.post.title';
|
||||
args.label = 'topic.reply.title';
|
||||
}
|
||||
|
||||
return args;
|
||||
|
||||
@ -27,6 +27,10 @@ const icons = {
|
||||
'private_topic': 'envelope'
|
||||
};
|
||||
|
||||
export function addPostSmallActionIcon(key, icon) {
|
||||
icons[key] = icon;
|
||||
};
|
||||
|
||||
export default createWidget('post-small-action', {
|
||||
buildKey: attrs => `post-small-act-${attrs.id}`,
|
||||
tagName: 'div.small-action.onscreen-post.clearfix',
|
||||
|
||||
@ -85,7 +85,7 @@ export default createWidget('search-menu', {
|
||||
|
||||
query += `q=${encodeURIComponent(searchData.term)}`;
|
||||
|
||||
if (contextEnabled) {
|
||||
if (contextEnabled && ctx) {
|
||||
if (this.currentUser &&
|
||||
ctx.id.toString().toLowerCase() === this.currentUser.username_lower &&
|
||||
type === "private_messages") {
|
||||
|
||||
@ -377,7 +377,7 @@ export default createWidget('topic-timeline', {
|
||||
controls.push(this.attach('button', {
|
||||
className: 'btn create',
|
||||
icon: 'reply',
|
||||
title: 'topic.reply.topic.help',
|
||||
title: 'topic.reply.help',
|
||||
action: 'replyToPost'
|
||||
}));
|
||||
}
|
||||
|
||||
@ -125,6 +125,17 @@ export function createWidget(name, opts) {
|
||||
return result;
|
||||
}
|
||||
|
||||
export function reopenWidget(name, opts) {
|
||||
let existing = _registry[name];
|
||||
if (!existing) {
|
||||
console.error(`Could not find widget ${name} in registry`);
|
||||
return;
|
||||
}
|
||||
|
||||
Object.keys(opts).forEach(k => existing.prototype[k] = opts[k]);
|
||||
return existing;
|
||||
}
|
||||
|
||||
export default class Widget {
|
||||
constructor(attrs, register, opts) {
|
||||
opts = opts || {};
|
||||
@ -145,12 +156,12 @@ export default class Widget {
|
||||
this.keyValueStore = register.lookup('key-value-store:main');
|
||||
|
||||
// Helps debug widgets
|
||||
if (Ember.testing) {
|
||||
if (Discourse.Environment === "development" || Ember.testing) {
|
||||
const ds = this.defaultState(attrs);
|
||||
if (typeof ds !== "object") {
|
||||
Ember.warn(`defaultState must return an object`);
|
||||
throw `defaultState must return an object`;
|
||||
} else if (Object.keys(ds).length > 0 && !this.key) {
|
||||
Ember.warn(`you need a key when using state ${this.name}`);
|
||||
throw `you need a key when using state in ${this.name}`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
function escapeRegexp(text) {
|
||||
return text.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
|
||||
}
|
||||
|
||||
export function censor(text, censoredWords, censoredPattern) {
|
||||
let patterns = [],
|
||||
originalText = text;
|
||||
|
||||
if (censoredWords && censoredWords.length) {
|
||||
patterns = censoredWords.split("|").map(t => { return "(" + t.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&') + ")"; });
|
||||
patterns = censoredWords.split("|").map(t => `(${escapeRegexp(t)})`);
|
||||
}
|
||||
|
||||
if (censoredPattern && censoredPattern.length > 0) {
|
||||
@ -22,7 +26,7 @@ export function censor(text, censoredWords, censoredPattern) {
|
||||
while (m && m[0]) {
|
||||
if (m[0].length > originalText.length) { return originalText; } // regex is dangerous
|
||||
const replacement = new Array(m[0].length+1).join('■');
|
||||
text = text.replace(new RegExp("(\\b" + m[0] + "\\b)(?![^\\(]*\\))", "ig"), replacement);
|
||||
text = text.replace(new RegExp(`(\\b${escapeRegexp(m[0])}\\b)(?![^\\(]*\\))`, "ig"), replacement);
|
||||
m = censorRegexp.exec(text);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,15 @@
|
||||
min-width: 96px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#revision {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#revision-controls {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#revisions .row:first-of-type {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
@ -64,6 +64,15 @@ $input-width: 220px;
|
||||
}
|
||||
}
|
||||
|
||||
.password-reset {
|
||||
.instructions {
|
||||
label {
|
||||
color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 50%));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// alternate login / create new account buttons should be de-emphasized
|
||||
|
||||
button#login-link, button#new-account-link
|
||||
|
||||
@ -14,7 +14,7 @@ a.loading-onebox {
|
||||
@include post-aside;
|
||||
|
||||
margin-top: 15px;
|
||||
padding: 12px 25px 12px 12px;
|
||||
padding: 12px;
|
||||
font-size: 1em;
|
||||
> .source {
|
||||
margin-bottom: 12px;
|
||||
@ -292,20 +292,22 @@ aside.onebox.twitterstatus .onebox-body {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// thumbnail, oddly, ONLY applies to twitter avatar
|
||||
.onebox.twitterstatus {
|
||||
.thumbnail {
|
||||
float: left;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
}
|
||||
p, .tweet {
|
||||
float: left;
|
||||
display: inline-block;
|
||||
white-space: pre-wrap;
|
||||
padding-top: 3px;
|
||||
width: 85%;
|
||||
margin-left: 58px;
|
||||
}
|
||||
.date {
|
||||
clear: left;
|
||||
padding-top: 5px;
|
||||
margin-left: 58px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -357,14 +359,29 @@ aside.onebox.stackexchange .onebox-body {
|
||||
color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 50%));
|
||||
}
|
||||
|
||||
// mobile specific style
|
||||
.mobile-view article.onebox-body {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.onebox.xkcd .onebox-body {
|
||||
img {
|
||||
max-width: 100% !important;
|
||||
float: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
// pdf onebox
|
||||
.onebox.pdf .onebox-body {
|
||||
.pdf-onebox-logo {
|
||||
width: 60px;
|
||||
height: 50px;
|
||||
float: left;
|
||||
background: image-url("favicons/pdf_64px.png") no-repeat;
|
||||
background-size: 48px 48px;
|
||||
display: inline-block;
|
||||
}
|
||||
.filesize {
|
||||
color: gray;
|
||||
}
|
||||
}
|
||||
|
||||
// mobile specific style
|
||||
.mobile-view article.onebox-body {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
@ -8,6 +8,8 @@
|
||||
}
|
||||
#revision-controls {
|
||||
float: left;
|
||||
padding-right: 5px;
|
||||
|
||||
.btn[disabled] {
|
||||
cursor: not-allowed;
|
||||
background-color: dark-light-diff($primary, $secondary, 90%, -60%);
|
||||
@ -18,6 +20,9 @@
|
||||
}
|
||||
#display-modes {
|
||||
text-align: right;
|
||||
display: inline-block;
|
||||
float: right;
|
||||
|
||||
.btn {
|
||||
background-color:inherit;
|
||||
color: dark-light-diff($primary, $secondary, 50%, -50%);
|
||||
|
||||
@ -43,12 +43,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
tr.instructions {
|
||||
label {
|
||||
color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 50%));
|
||||
}
|
||||
}
|
||||
|
||||
.tos-agree {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
@ -57,4 +51,24 @@
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.instructions {
|
||||
label {
|
||||
color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 50%));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.password-reset {
|
||||
.col-form {
|
||||
padding-top: 40px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
h2 {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.password-reset-img {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -442,6 +442,10 @@ a.star {
|
||||
}
|
||||
}
|
||||
|
||||
#topic-footer-button {
|
||||
width: 757px;
|
||||
}
|
||||
|
||||
#suggested-topics {
|
||||
clear: left;
|
||||
padding: 20px 0 15px 0;
|
||||
|
||||
@ -84,3 +84,32 @@ $input-width: 184px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.password-reset {
|
||||
margin-top: 30px;
|
||||
.col-image {
|
||||
padding-top: 12px;
|
||||
}
|
||||
.password-reset-img {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
.col-form {
|
||||
padding-left: 8px;
|
||||
}
|
||||
h2 {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.tip {
|
||||
display: block;
|
||||
margin: 6px 0;
|
||||
max-width: 180px;
|
||||
}
|
||||
}
|
||||
|
||||
.discourse-touch .password-reset {
|
||||
.instructions {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -330,6 +330,11 @@ a.star {
|
||||
color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 50%));
|
||||
}
|
||||
|
||||
#topic-footer-button {
|
||||
width: 100px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#suggested-topics {
|
||||
clear: left;
|
||||
padding: 20px 0 15px 0;
|
||||
|
||||
@ -72,8 +72,7 @@ class Admin::UsersController < Admin::AdminController
|
||||
|
||||
def log_out
|
||||
if @user
|
||||
@user.auth_token = nil
|
||||
@user.save!
|
||||
@user.user_auth_tokens.destroy_all
|
||||
@user.logged_out
|
||||
render json: success_json
|
||||
else
|
||||
|
||||
@ -18,12 +18,7 @@ class GroupsController < ApplicationController
|
||||
page_size = 30
|
||||
page = params[:page]&.to_i || 0
|
||||
|
||||
groups = Group.order(name: :asc).where(visible: true)
|
||||
|
||||
if !guardian.is_admin?
|
||||
groups = groups.where(automatic: false)
|
||||
end
|
||||
|
||||
groups = Group.visible_groups(current_user)
|
||||
count = groups.count
|
||||
groups = groups.offset(page * page_size).limit(page_size)
|
||||
|
||||
|
||||
@ -48,8 +48,8 @@ class InvitesController < ApplicationController
|
||||
guardian.ensure_can_invite_to_forum!(group_ids)
|
||||
|
||||
invite_exists = Invite.where(email: params[:email], invited_by_id: current_user.id).first
|
||||
if invite_exists
|
||||
guardian.ensure_can_send_multiple_invites!(current_user)
|
||||
if invite_exists && !guardian.can_send_multiple_invites?(current_user)
|
||||
return render json: failed_json, status: 422
|
||||
end
|
||||
|
||||
begin
|
||||
@ -70,8 +70,8 @@ class InvitesController < ApplicationController
|
||||
guardian.ensure_can_invite_to_forum!(group_ids)
|
||||
|
||||
invite_exists = Invite.where(email: params[:email], invited_by_id: current_user.id).first
|
||||
if invite_exists
|
||||
guardian.ensure_can_send_multiple_invites!(current_user)
|
||||
if invite_exists && !guardian.can_send_multiple_invites?(current_user)
|
||||
return render json: failed_json, status: 422
|
||||
end
|
||||
|
||||
begin
|
||||
|
||||
@ -17,7 +17,7 @@ class MetadataController < ApplicationController
|
||||
name: SiteSetting.title,
|
||||
short_name: SiteSetting.title,
|
||||
display: 'standalone',
|
||||
orientation: 'any',
|
||||
orientation: 'natural',
|
||||
start_url: "#{Discourse.base_uri}/",
|
||||
background_color: "##{ColorScheme.hex_for_name('secondary')}",
|
||||
theme_color: "##{ColorScheme.hex_for_name('header_background')}",
|
||||
|
||||
@ -74,13 +74,13 @@ class UploadsController < ApplicationController
|
||||
return { errors: I18n.t("upload.file_missing") } if tempfile.nil?
|
||||
|
||||
# convert pasted images to HQ jpegs
|
||||
if filename == "blob.png" && SiteSetting.convert_pasted_images_to_hq_jpg
|
||||
jpeg_path = "#{File.dirname(tempfile.path)}/blob.jpg"
|
||||
if filename == "image.png" && SiteSetting.convert_pasted_images_to_hq_jpg
|
||||
jpeg_path = "#{File.dirname(tempfile.path)}/image.jpg"
|
||||
OptimizedImage.ensure_safe_paths!(tempfile.path, jpeg_path)
|
||||
`convert #{tempfile.path} -quality #{SiteSetting.convert_pasted_images_quality} #{jpeg_path}`
|
||||
# only change the format of the image when JPG is at least 5% smaller
|
||||
if File.size(jpeg_path) < File.size(tempfile.path) * 0.95
|
||||
filename = "blob.jpg"
|
||||
filename = "image.jpg"
|
||||
content_type = "image/jpeg"
|
||||
tempfile = File.open(jpeg_path)
|
||||
else
|
||||
|
||||
@ -405,8 +405,6 @@ class UsersController < ApplicationController
|
||||
user_id = secure_session["password-#{token}"].to_i
|
||||
@user = User.find(user_id) if user_id > 0
|
||||
end
|
||||
else
|
||||
@invalid_token = true
|
||||
end
|
||||
|
||||
if !@user
|
||||
@ -419,17 +417,47 @@ class UsersController < ApplicationController
|
||||
else
|
||||
@user.password = params[:password]
|
||||
@user.password_required!
|
||||
@user.auth_token = nil
|
||||
@user.user_auth_tokens.destroy_all
|
||||
if @user.save
|
||||
Invite.invalidate_for_email(@user.email) # invite link can't be used to log in anymore
|
||||
secure_session["password-#{token}"] = nil
|
||||
logon_after_password_reset
|
||||
|
||||
return redirect_to(wizard_path) if Wizard.user_requires_completion?(@user)
|
||||
end
|
||||
end
|
||||
end
|
||||
render layout: 'no_ember'
|
||||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
if @error
|
||||
render layout: 'no_ember'
|
||||
else
|
||||
store_preloaded("password_reset", MultiJson.dump({ is_developer: UsernameCheckerService.is_developer?(@user.email) }))
|
||||
end
|
||||
return redirect_to(wizard_path) if Wizard.user_requires_completion?(@user)
|
||||
end
|
||||
|
||||
format.json do
|
||||
if request.put?
|
||||
if @error || @user&.errors&.any?
|
||||
render json: {
|
||||
success: false,
|
||||
message: @error,
|
||||
errors: @user&.errors&.to_hash,
|
||||
is_developer: UsernameCheckerService.is_developer?(@user.email)
|
||||
}
|
||||
else
|
||||
render json: {
|
||||
success: true,
|
||||
message: @success,
|
||||
requires_approval: !Guardian.new(@user).can_access_forum?,
|
||||
redirect_to: Wizard.user_requires_completion?(@user) ? wizard_path : nil
|
||||
}
|
||||
end
|
||||
else
|
||||
render json: {is_developer: UsernameCheckerService.is_developer?(@user.email)}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def confirm_email_token
|
||||
@ -559,7 +587,17 @@ class UsersController < ApplicationController
|
||||
topic_id = topic_id.to_i if topic_id
|
||||
topic_allowed_users = params[:topic_allowed_users] || false
|
||||
|
||||
results = UserSearch.new(term, topic_id: topic_id, topic_allowed_users: topic_allowed_users, searching_user: current_user).search
|
||||
if params[:group].present?
|
||||
@group = Group.find_by(name: params[:group])
|
||||
end
|
||||
|
||||
|
||||
results = UserSearch.new(term,
|
||||
topic_id: topic_id,
|
||||
topic_allowed_users: topic_allowed_users,
|
||||
searching_user: current_user,
|
||||
group: @group
|
||||
).search
|
||||
|
||||
user_fields = [:username, :upload_avatar_template]
|
||||
user_fields << :name if SiteSetting.enable_names?
|
||||
@ -673,7 +711,7 @@ class UsersController < ApplicationController
|
||||
private
|
||||
|
||||
def honeypot_value
|
||||
Digest::SHA1::hexdigest("#{Discourse.current_hostname}:#{Discourse::Application.config.secret_token}")[0,15]
|
||||
Digest::SHA1::hexdigest("#{Discourse.current_hostname}:#{GlobalSetting.safe_secret_key_base}")[0,15]
|
||||
end
|
||||
|
||||
def challenge_value
|
||||
|
||||
@ -24,14 +24,15 @@ class WebhooksController < ActionController::Base
|
||||
|
||||
event = params["event"]
|
||||
message_id = params["Message-Id"].tr("<>", "")
|
||||
to_address = params["recipient"]
|
||||
|
||||
# only handle soft bounces, because hard bounces are also handled
|
||||
# by the "dropped" event and we don't want to increase bounce score twice
|
||||
# for the same message
|
||||
if event == "bounced".freeze && params["error"]["4."]
|
||||
process_bounce(message_id, SiteSetting.soft_bounce_score)
|
||||
process_bounce(message_id, to_address, SiteSetting.soft_bounce_score)
|
||||
elsif event == "dropped".freeze
|
||||
process_bounce(message_id, SiteSetting.hard_bounce_score)
|
||||
process_bounce(message_id, to_address, SiteSetting.hard_bounce_score)
|
||||
end
|
||||
|
||||
mailgun_success
|
||||
@ -41,14 +42,15 @@ class WebhooksController < ActionController::Base
|
||||
events = params["_json"] || [params]
|
||||
events.each do |event|
|
||||
message_id = (event["smtp-id"] || "").tr("<>", "")
|
||||
to_address = event["email"]
|
||||
if event["event"] == "bounce".freeze
|
||||
if event["status"]["4."]
|
||||
process_bounce(message_id, SiteSetting.soft_bounce_score)
|
||||
process_bounce(message_id, to_address, SiteSetting.soft_bounce_score)
|
||||
else
|
||||
process_bounce(message_id, SiteSetting.hard_bounce_score)
|
||||
process_bounce(message_id, to_address, SiteSetting.hard_bounce_score)
|
||||
end
|
||||
elsif event["event"] == "dropped".freeze
|
||||
process_bounce(message_id, SiteSetting.hard_bounce_score)
|
||||
process_bounce(message_id, to_address, SiteSetting.hard_bounce_score)
|
||||
end
|
||||
end
|
||||
|
||||
@ -59,11 +61,12 @@ class WebhooksController < ActionController::Base
|
||||
events = params["_json"] || [params]
|
||||
events.each do |event|
|
||||
message_id = event["CustomID"]
|
||||
to_address = event["email"]
|
||||
if event["event"] == "bounce".freeze
|
||||
if event["hard_bounce"]
|
||||
process_bounce(message_id, SiteSetting.hard_bounce_score)
|
||||
process_bounce(message_id, to_address, SiteSetting.hard_bounce_score)
|
||||
else
|
||||
process_bounce(message_id, SiteSetting.soft_bounce_score)
|
||||
process_bounce(message_id, to_address, SiteSetting.soft_bounce_score)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -75,13 +78,13 @@ class WebhooksController < ActionController::Base
|
||||
events = params["mandrill_events"]
|
||||
events.each do |event|
|
||||
message_id = event["msg"]["metadata"]["message_id"] rescue nil
|
||||
next unless message_id
|
||||
to_address = event["msg"]["email"] rescue nil
|
||||
|
||||
case event["event"]
|
||||
when "hard_bounce"
|
||||
process_bounce(message_id, SiteSetting.hard_bounce_score)
|
||||
process_bounce(message_id, to_address, SiteSetting.hard_bounce_score)
|
||||
when "soft_bounce"
|
||||
process_bounce(message_id, SiteSetting.soft_bounce_score)
|
||||
process_bounce(message_id, to_address, SiteSetting.soft_bounce_score)
|
||||
end
|
||||
end
|
||||
|
||||
@ -91,18 +94,22 @@ class WebhooksController < ActionController::Base
|
||||
def sparkpost
|
||||
events = params["_json"] || [params]
|
||||
events.each do |event|
|
||||
message_id = event["msys"]["message_event"]["rcpt_meta"]["message_id"] rescue nil
|
||||
bounce_class = event["msys"]["message_event"]["bounce_class"] rescue nil
|
||||
next unless message_id && bounce_class
|
||||
message_event = event["msys"]["message_event"] rescue nil
|
||||
next unless message_event
|
||||
|
||||
message_id = message_event["rcpt_meta"]["message_id"] rescue nil
|
||||
to_address = message_event["rcpt_to"] rescue nil
|
||||
bounce_class = message_event["bounce_class"] rescue nil
|
||||
next unless bounce_class
|
||||
|
||||
bounce_class = bounce_class.to_i
|
||||
|
||||
# bounce class definitions: https://support.sparkpost.com/customer/portal/articles/1929896
|
||||
if bounce_class < 80
|
||||
if bounce_class == 10 || bounce_class == 25 || bounce_class == 30
|
||||
process_bounce(message_id, SiteSetting.hard_bounce_score)
|
||||
process_bounce(message_id, to_address, SiteSetting.hard_bounce_score)
|
||||
else
|
||||
process_bounce(message_id, SiteSetting.soft_bounce_score)
|
||||
process_bounce(message_id, to_address, SiteSetting.soft_bounce_score)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -126,10 +133,10 @@ class WebhooksController < ActionController::Base
|
||||
signature == OpenSSL::HMAC.hexdigest(digest, SiteSetting.mailgun_api_key, data)
|
||||
end
|
||||
|
||||
def process_bounce(message_id, bounce_score)
|
||||
return if message_id.blank?
|
||||
def process_bounce(message_id, to_address, bounce_score)
|
||||
return if message_id.blank? || to_address.blank?
|
||||
|
||||
email_log = EmailLog.find_by(message_id: message_id)
|
||||
email_log = EmailLog.find_by(message_id: message_id, to_address: to_address)
|
||||
return if email_log.nil?
|
||||
|
||||
email_log.update_columns(bounced: true)
|
||||
|
||||
@ -15,13 +15,6 @@ module TopicsHelper
|
||||
breadcrumb.push url: category.url, name: category.name
|
||||
end
|
||||
|
||||
if SiteSetting.tagging_enabled && (tags = topic.tags).present?
|
||||
tags.each do |tag|
|
||||
url = "#{Discourse.base_url}/tags/#{tag.name}"
|
||||
breadcrumb << {url: url, name: tag.name}
|
||||
end
|
||||
end
|
||||
|
||||
Plugin::Filter.apply(:topic_categories_breadcrumb, topic, breadcrumb)
|
||||
end
|
||||
|
||||
|
||||
@ -33,11 +33,17 @@ module Jobs
|
||||
Rails.logger.warn("Cooked post processor in FATAL state, bypassing. You need to urgently restart sidekiq\norig: #{orig_cooked}\nrecooked: #{recooked}\ncooked: #{cooked}\npost id: #{post.id}")
|
||||
else
|
||||
post.update_column(:cooked, cp.html)
|
||||
extract_links(post)
|
||||
post.publish_change_to_clients! :revised
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# onebox may have added some links, so extract them now
|
||||
def extract_links(post)
|
||||
TopicLink.extract_from(post)
|
||||
QuotedPost.extract_from(post)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -21,7 +21,7 @@ module Jobs
|
||||
.where(user_options: {email_digests: true})
|
||||
.where("COALESCE(last_emailed_at, '2010-01-01') <= CURRENT_TIMESTAMP - ('1 MINUTE'::INTERVAL * user_options.digest_after_minutes)")
|
||||
.where("COALESCE(last_seen_at, '2010-01-01') <= CURRENT_TIMESTAMP - ('1 MINUTE'::INTERVAL * user_options.digest_after_minutes)")
|
||||
.where("COALESCE(last_seen_at, '2010-01-01') >= CURRENT_TIMESTAMP - ('1 DAY'::INTERVAL * #{SiteSetting.delete_digest_email_after_days})")
|
||||
.where("COALESCE(last_seen_at, '2010-01-01') >= CURRENT_TIMESTAMP - ('1 DAY'::INTERVAL * #{SiteSetting.suppress_digest_email_after_days})")
|
||||
|
||||
# If the site requires approval, make sure the user is approved
|
||||
if SiteSetting.must_approve_users?
|
||||
|
||||
@ -13,6 +13,7 @@ module Jobs
|
||||
ScoreCalculator.new.calculate
|
||||
SchedulerStat.purge_old
|
||||
Draft.cleanup!
|
||||
UserAuthToken.cleanup!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -74,6 +74,7 @@ class UserNotifications < ActionMailer::Base
|
||||
end
|
||||
end
|
||||
|
||||
# This is the "mailing list summary email"
|
||||
def mailing_list(user, opts={})
|
||||
@since = opts[:since] || 1.day.ago
|
||||
@since_formatted = short_date(@since)
|
||||
|
||||
@ -79,6 +79,8 @@ class DiscourseSingleSignOn < SingleSignOn
|
||||
user.admin = admin unless admin.nil?
|
||||
user.moderator = moderator unless moderator.nil?
|
||||
|
||||
user.title = title unless title.nil?
|
||||
|
||||
# optionally save the user and sso_record if they have changed
|
||||
user.user_avatar.save! if user.user_avatar
|
||||
user.save!
|
||||
|
||||
@ -6,6 +6,35 @@ class GlobalSetting
|
||||
end
|
||||
end
|
||||
|
||||
VALID_SECRET_KEY = /^[0-9a-f]{128}$/
|
||||
# this is named SECRET_TOKEN as opposed to SECRET_KEY_BASE
|
||||
# for legacy reasons
|
||||
REDIS_SECRET_KEY = 'SECRET_TOKEN'
|
||||
|
||||
# In Rails secret_key_base is used to encrypt the cookie store
|
||||
# the cookie store contains session data
|
||||
# Discourse also uses this secret key to digest user auth tokens
|
||||
# This method will
|
||||
# - use existing token if already set in ENV or discourse.conf
|
||||
# - generate a token on the fly if needed and cache in redis
|
||||
# - enforce rules about token format falling back to redis if needed
|
||||
def self.safe_secret_key_base
|
||||
@safe_secret_key_base ||= begin
|
||||
token = secret_key_base
|
||||
if token.blank? || token !~ VALID_SECRET_KEY
|
||||
token = $redis.without_namespace.get(REDIS_SECRET_KEY)
|
||||
unless token && token =~ VALID_SECRET_KEY
|
||||
token = SecureRandom.hex(64)
|
||||
$redis.without_namespace.set(REDIS_SECRET_KEY,token)
|
||||
end
|
||||
end
|
||||
if !secret_key_base.blank? && token != secret_key_base
|
||||
STDERR.puts "WARNING: DISCOURSE_SECRET_KEY_BASE is invalid, it was re-generated"
|
||||
end
|
||||
token
|
||||
end
|
||||
end
|
||||
|
||||
def self.load_defaults
|
||||
default_provider = FileProvider.from(File.expand_path('../../../config/discourse_defaults.conf', __FILE__))
|
||||
default_provider.keys.concat(@provider.keys).uniq.each do |key|
|
||||
@ -37,29 +66,39 @@ class GlobalSetting
|
||||
{"production" => hash}
|
||||
end
|
||||
|
||||
# For testing purposes
|
||||
def self.reset_redis_config!
|
||||
@config = nil
|
||||
end
|
||||
|
||||
def self.redis_config
|
||||
@config ||=
|
||||
begin
|
||||
c = {}
|
||||
c[:host] = redis_host if redis_host
|
||||
c[:port] = redis_port if redis_port
|
||||
c[:slave_host] = redis_slave_host if redis_slave_host
|
||||
c[:slave_port] = redis_slave_port if redis_slave_port
|
||||
|
||||
if redis_slave_host && redis_slave_port
|
||||
c[:slave_host] = redis_slave_host
|
||||
c[:slave_port] = redis_slave_port
|
||||
c[:connector] = DiscourseRedis::Connector
|
||||
end
|
||||
|
||||
c[:password] = redis_password if redis_password.present?
|
||||
c[:db] = redis_db if redis_db != 0
|
||||
c[:db] = 1 if Rails.env == "test"
|
||||
|
||||
if redis_sentinels.present?
|
||||
c[:sentinels] = redis_sentinels.split(",").map do |address|
|
||||
host,port = address.split(":")
|
||||
{host: host, port: port}
|
||||
end.to_a
|
||||
end
|
||||
c[:connector] = DiscourseRedis::Connector
|
||||
|
||||
c.freeze
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class BaseProvider
|
||||
def self.coerce(setting)
|
||||
return setting == "true" if setting == "true" || setting == "false"
|
||||
|
||||
@ -63,6 +63,20 @@ class Group < ActiveRecord::Base
|
||||
|
||||
validates :alias_level, inclusion: { in: ALIAS_LEVELS.values}
|
||||
|
||||
scope :visible_groups, ->(user) {
|
||||
groups = Group.order(name: :asc).where("groups.id > 0")
|
||||
|
||||
if !user || !user.admin
|
||||
owner_group_ids = GroupUser.where(user: user, owner: true).pluck(:group_id)
|
||||
|
||||
groups = groups.where("
|
||||
(groups.automatic = false AND groups.visible = true) OR groups.id IN (?)
|
||||
", owner_group_ids)
|
||||
end
|
||||
|
||||
groups
|
||||
}
|
||||
|
||||
scope :mentionable, lambda {|user|
|
||||
|
||||
levels = [ALIAS_LEVELS[:everyone]]
|
||||
|
||||
@ -59,7 +59,7 @@ class Invite < ActiveRecord::Base
|
||||
if topic.private_message?
|
||||
topic.grant_permission_to_user(user.email)
|
||||
elsif topic.category && topic.category.groups.any?
|
||||
if Guardian.new(invited_by).can_invite_to?(topic) && !SiteSetting.enable_sso
|
||||
if Guardian.new(invited_by).can_invite_via_email?(topic)
|
||||
(topic.category.groups - user.groups).each do |group|
|
||||
group.add(user)
|
||||
GroupActionLogger.new(Discourse.system_user, group).log_add_user_to_group(user)
|
||||
|
||||
@ -454,7 +454,7 @@ class Post < ActiveRecord::Base
|
||||
new_cooked = cook(raw, topic_id: topic_id, invalidate_oneboxes: opts.fetch(:invalidate_oneboxes, false))
|
||||
old_cooked = cooked
|
||||
|
||||
self.update!(cooked: new_cooked, baked_at: Time.new, baked_version: BAKED_VERSION)
|
||||
update_columns(cooked: new_cooked, baked_at: Time.new, baked_version: BAKED_VERSION)
|
||||
|
||||
# Extracts urls from the body
|
||||
TopicLink.extract_from(self)
|
||||
|
||||
@ -744,7 +744,7 @@ SQL
|
||||
end
|
||||
end
|
||||
|
||||
if username_or_email =~ /^.+@.+$/ && !SiteSetting.enable_sso && SiteSetting.enable_local_logins
|
||||
if username_or_email =~ /^.+@.+$/ && Guardian.new(invited_by).can_invite_via_email?(self)
|
||||
# rate limit topic invite
|
||||
RateLimiter.new(invited_by, "topic-invitations-per-day", SiteSetting.max_topic_invitations_per_day, 1.day.to_i).performed!
|
||||
|
||||
@ -829,6 +829,9 @@ SQL
|
||||
previous_banner = Topic.where(archetype: Archetype.banner).first
|
||||
previous_banner.remove_banner!(user) if previous_banner.present?
|
||||
|
||||
UserProfile.where("dismissed_banner_key IS NOT NULL")
|
||||
.update_all(dismissed_banner_key: nil)
|
||||
|
||||
self.archetype = Archetype.banner
|
||||
self.add_moderator_post(user, I18n.t("archetypes.banner.message.make"))
|
||||
self.save
|
||||
@ -1118,6 +1121,7 @@ SQL
|
||||
builder.where("p.post_number > 1")
|
||||
builder.where("p.user_id != t.user_id")
|
||||
builder.where("p.user_id in (:user_ids)", {user_ids: opts[:user_ids]}) if opts[:user_ids]
|
||||
builder.where("p.post_type = :post_type", post_type: Post.types[:regular])
|
||||
builder.where("EXTRACT(EPOCH FROM p.created_at - t.created_at) > 0")
|
||||
builder.exec
|
||||
end
|
||||
@ -1136,11 +1140,11 @@ SQL
|
||||
FROM (
|
||||
SELECT t.id, t.created_at::date AS created_at, MIN(p.post_number) first_reply
|
||||
FROM topics t
|
||||
LEFT JOIN posts p ON p.topic_id = t.id AND p.user_id != t.user_id AND p.deleted_at IS NULL
|
||||
LEFT JOIN posts p ON p.topic_id = t.id AND p.user_id != t.user_id AND p.deleted_at IS NULL AND p.post_type = #{Post.types[:regular]}
|
||||
/*where*/
|
||||
GROUP BY t.id
|
||||
) tt
|
||||
WHERE tt.first_reply IS NULL
|
||||
WHERE tt.first_reply IS NULL OR tt.first_reply < 2
|
||||
GROUP BY tt.created_at
|
||||
ORDER BY tt.created_at
|
||||
SQL
|
||||
@ -1160,11 +1164,11 @@ SQL
|
||||
FROM (
|
||||
SELECT t.id, MIN(p.post_number) first_reply
|
||||
FROM topics t
|
||||
LEFT JOIN posts p ON p.topic_id = t.id AND p.user_id != t.user_id AND p.deleted_at IS NULL
|
||||
LEFT JOIN posts p ON p.topic_id = t.id AND p.user_id != t.user_id AND p.deleted_at IS NULL AND p.post_type = #{Post.types[:regular]}
|
||||
/*where*/
|
||||
GROUP BY t.id
|
||||
) tt
|
||||
WHERE tt.first_reply IS NULL
|
||||
WHERE tt.first_reply IS NULL OR tt.first_reply < 2
|
||||
SQL
|
||||
|
||||
def self.with_no_response_total(opts={})
|
||||
|
||||
@ -41,6 +41,7 @@ class User < ActiveRecord::Base
|
||||
has_many :user_archived_messages, dependent: :destroy
|
||||
has_many :email_change_requests, dependent: :destroy
|
||||
has_many :directory_items, dependent: :delete_all
|
||||
has_many :user_auth_tokens, dependent: :destroy
|
||||
|
||||
|
||||
has_one :user_option, dependent: :destroy
|
||||
@ -97,6 +98,7 @@ class User < ActiveRecord::Base
|
||||
before_save :update_username_lower
|
||||
before_save :ensure_password_is_hashed
|
||||
|
||||
after_save :expire_tokens_if_password_changed
|
||||
after_save :automatic_group_membership
|
||||
after_save :clear_global_notice_if_needed
|
||||
after_save :refresh_avatar
|
||||
@ -420,7 +422,6 @@ class User < ActiveRecord::Base
|
||||
# special case for passwordless accounts
|
||||
unless password.blank?
|
||||
@raw_password = password
|
||||
self.auth_token = nil
|
||||
end
|
||||
end
|
||||
|
||||
@ -922,6 +923,8 @@ class User < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def clear_global_notice_if_needed
|
||||
return if id == Discourse::SYSTEM_USER_ID
|
||||
|
||||
if admin && SiteSetting.has_login_hint
|
||||
SiteSetting.has_login_hint = false
|
||||
SiteSetting.global_notice = ""
|
||||
@ -933,14 +936,17 @@ class User < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def automatic_group_membership
|
||||
user = User.find(self.id)
|
||||
|
||||
return unless user && user.active && !user.staged
|
||||
|
||||
Group.where(automatic: false)
|
||||
.where("LENGTH(COALESCE(automatic_membership_email_domains, '')) > 0")
|
||||
.each do |group|
|
||||
|
||||
domains = group.automatic_membership_email_domains.gsub('.', '\.')
|
||||
user = User.find(self.id)
|
||||
|
||||
if user.reload.email =~ Regexp.new("@(#{domains})$", true) && !group.users.include?(user)
|
||||
if user.email =~ Regexp.new("@(#{domains})$", true) && !group.users.include?(user)
|
||||
group.add(user)
|
||||
GroupActionLogger.new(Discourse.system_user, group).log_add_user_to_group(user)
|
||||
end
|
||||
@ -968,6 +974,18 @@ class User < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def expire_tokens_if_password_changed
|
||||
# NOTE: setting raw password is the only valid way of changing a password
|
||||
# the password field in the DB is actually hashed, nobody should be amending direct
|
||||
if @raw_password
|
||||
# Association in model may be out-of-sync
|
||||
UserAuthToken.where(user_id: id).destroy_all
|
||||
# We should not carry this around after save
|
||||
@raw_password = nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def hash_password(password, salt)
|
||||
raise StandardError.new("password is too long") if password.size > User.max_password_length
|
||||
Pbkdf2.hash_password(password, salt, Rails.configuration.pbkdf2_iterations, Rails.configuration.pbkdf2_algorithm)
|
||||
@ -1073,7 +1091,7 @@ end
|
||||
# username :string(60) not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# name :string
|
||||
# name :string(255)
|
||||
# seen_notification_id :integer default(0), not null
|
||||
# last_posted_at :datetime
|
||||
# email :string(513) not null
|
||||
@ -1098,7 +1116,7 @@ end
|
||||
# ip_address :inet
|
||||
# moderator :boolean default(FALSE)
|
||||
# blocked :boolean default(FALSE)
|
||||
# title :string
|
||||
# title :string(255)
|
||||
# uploaded_avatar_id :integer
|
||||
# locale :string(10)
|
||||
# primary_group_id :integer
|
||||
|
||||
@ -19,6 +19,7 @@ class UserAction < ActiveRecord::Base
|
||||
GOT_PRIVATE_MESSAGE = 13
|
||||
PENDING = 14
|
||||
SOLVED = 15
|
||||
ASSIGNED = 16
|
||||
|
||||
ORDER = Hash[*[
|
||||
GOT_PRIVATE_MESSAGE,
|
||||
@ -34,6 +35,7 @@ class UserAction < ActiveRecord::Base
|
||||
BOOKMARK,
|
||||
EDIT,
|
||||
SOLVED,
|
||||
ASSIGNED,
|
||||
].each_with_index.to_a.flatten]
|
||||
|
||||
# note, this is temporary until we upgrade to rails 4
|
||||
|
||||
170
app/models/user_auth_token.rb
Normal file
170
app/models/user_auth_token.rb
Normal file
@ -0,0 +1,170 @@
|
||||
# frozen_string_literal: true
|
||||
require 'digest/sha1'
|
||||
|
||||
class UserAuthToken < ActiveRecord::Base
|
||||
belongs_to :user
|
||||
|
||||
ROTATE_TIME = 10.minutes
|
||||
# used when token did not arrive at client
|
||||
URGENT_ROTATE_TIME = 1.minute
|
||||
|
||||
attr_accessor :unhashed_auth_token
|
||||
|
||||
def self.generate!(info)
|
||||
token = SecureRandom.hex(16)
|
||||
hashed_token = hash_token(token)
|
||||
user_auth_token = UserAuthToken.create!(
|
||||
user_id: info[:user_id],
|
||||
user_agent: info[:user_agent],
|
||||
client_ip: info[:client_ip],
|
||||
auth_token: hashed_token,
|
||||
prev_auth_token: hashed_token,
|
||||
rotated_at: Time.zone.now
|
||||
)
|
||||
user_auth_token.unhashed_auth_token = token
|
||||
|
||||
if SiteSetting.verbose_auth_token_logging
|
||||
UserAuthTokenLog.create!(
|
||||
action: 'generate',
|
||||
user_auth_token_id: user_auth_token.id,
|
||||
user_id: info[:user_id],
|
||||
user_agent: info[:user_agent],
|
||||
client_ip: info[:client_ip],
|
||||
auth_token: hashed_token
|
||||
)
|
||||
end
|
||||
|
||||
user_auth_token
|
||||
end
|
||||
|
||||
def self.lookup(unhashed_token, opts=nil)
|
||||
|
||||
mark_seen = opts && opts[:seen]
|
||||
|
||||
token = hash_token(unhashed_token)
|
||||
expire_before = SiteSetting.maximum_session_age.hours.ago
|
||||
|
||||
user_token = find_by("(auth_token = :token OR
|
||||
prev_auth_token = :token OR
|
||||
(auth_token = :unhashed_token AND legacy)) AND created_at > :expire_before",
|
||||
token: token, unhashed_token: unhashed_token, expire_before: expire_before)
|
||||
|
||||
token_expired =
|
||||
user_token &&
|
||||
user_token.auth_token_seen &&
|
||||
user_token.prev_auth_token == token &&
|
||||
user_token.prev_auth_token != user_token.auth_token &&
|
||||
user_token.rotated_at > 1.minute.ago
|
||||
|
||||
if token_expired || !user_token
|
||||
|
||||
if SiteSetting.verbose_auth_token_logging
|
||||
UserAuthTokenLog.create(
|
||||
action: "miss token",
|
||||
user_id: user_token&.user_id,
|
||||
auth_token: token,
|
||||
user_agent: opts && opts[:user_agent],
|
||||
client_ip: opts && opts[:client_ip]
|
||||
)
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
if mark_seen && user_token && !user_token.auth_token_seen && user_token.auth_token == token
|
||||
user_token.update_columns(auth_token_seen: true)
|
||||
|
||||
if SiteSetting.verbose_auth_token_logging
|
||||
UserAuthTokenLog.create(
|
||||
action: "seen token",
|
||||
user_auth_token_id: user_token.id,
|
||||
user_id: user_token.user_id,
|
||||
auth_token: user_token.auth_token,
|
||||
user_agent: opts && opts[:user_agent],
|
||||
client_ip: opts && opts[:client_ip]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
user_token
|
||||
end
|
||||
|
||||
def self.hash_token(token)
|
||||
Digest::SHA1.base64digest("#{token}#{GlobalSetting.safe_secret_key_base}")
|
||||
end
|
||||
|
||||
def self.cleanup!
|
||||
|
||||
if SiteSetting.verbose_auth_token_logging
|
||||
UserAuthTokenLog.where('created_at < :time',
|
||||
time: SiteSetting.maximum_session_age.hours.ago - ROTATE_TIME).delete_all
|
||||
end
|
||||
|
||||
where('rotated_at < :time',
|
||||
time: SiteSetting.maximum_session_age.hours.ago - ROTATE_TIME).delete_all
|
||||
|
||||
end
|
||||
|
||||
def rotate!(info=nil)
|
||||
user_agent = (info && info[:user_agent] || self.user_agent)
|
||||
client_ip = (info && info[:client_ip] || self.client_ip)
|
||||
|
||||
token = SecureRandom.hex(16)
|
||||
|
||||
result = UserAuthToken.exec_sql("
|
||||
UPDATE user_auth_tokens
|
||||
SET
|
||||
auth_token_seen = false,
|
||||
user_agent = :user_agent,
|
||||
client_ip = :client_ip,
|
||||
prev_auth_token = case when auth_token_seen then auth_token else prev_auth_token end,
|
||||
auth_token = :new_token,
|
||||
rotated_at = :now
|
||||
WHERE id = :id AND (auth_token_seen or rotated_at < :safeguard_time)
|
||||
", id: self.id,
|
||||
user_agent: user_agent,
|
||||
client_ip: client_ip&.to_s,
|
||||
now: Time.zone.now,
|
||||
new_token: UserAuthToken.hash_token(token),
|
||||
safeguard_time: 30.seconds.ago
|
||||
)
|
||||
|
||||
if result.cmdtuples > 0
|
||||
reload
|
||||
self.unhashed_auth_token = token
|
||||
|
||||
if SiteSetting.verbose_auth_token_logging
|
||||
UserAuthTokenLog.create(
|
||||
action: "rotate",
|
||||
user_auth_token_id: id,
|
||||
user_id: user_id,
|
||||
auth_token: auth_token,
|
||||
user_agent: user_agent,
|
||||
client_ip: client_ip
|
||||
)
|
||||
end
|
||||
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: user_auth_tokens
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer not null
|
||||
# auth_token :string not null
|
||||
# prev_auth_token :string
|
||||
# user_agent :string
|
||||
# auth_token_seen :boolean default(FALSE), not null
|
||||
# legacy :boolean default(FALSE), not null
|
||||
# client_ip :inet
|
||||
# rotated_at :datetime
|
||||
# created_at :datetime
|
||||
# updated_at :datetime
|
||||
#
|
||||
2
app/models/user_auth_token_log.rb
Normal file
2
app/models/user_auth_token_log.rb
Normal file
@ -0,0 +1,2 @@
|
||||
class UserAuthTokenLog < ActiveRecord::Base
|
||||
end
|
||||
@ -61,7 +61,8 @@ class UserHistory < ActiveRecord::Base
|
||||
activate_user: 43,
|
||||
change_readonly_mode: 44,
|
||||
backup_download: 45,
|
||||
backup_destroy: 46)
|
||||
backup_destroy: 46,
|
||||
notified_about_get_a_room: 47)
|
||||
end
|
||||
|
||||
# Staff actions is a subset of all actions, used to audit actions taken by staff users.
|
||||
|
||||
@ -10,11 +10,20 @@ class UserSearch
|
||||
@topic_allowed_users = opts[:topic_allowed_users]
|
||||
@searching_user = opts[:searching_user]
|
||||
@limit = opts[:limit] || 20
|
||||
@group = opts[:group]
|
||||
@guardian = Guardian.new(@searching_user)
|
||||
@guardian.ensure_can_see_group!(@group) if @group
|
||||
end
|
||||
|
||||
def scoped_users
|
||||
users = User.where(active: true, staged: false)
|
||||
|
||||
if @group
|
||||
users = users.where('users.id IN (
|
||||
SELECT user_id FROM group_users WHERE group_id = ?
|
||||
)', @group.id)
|
||||
end
|
||||
|
||||
unless @searching_user && @searching_user.staff?
|
||||
users = users.not_suspended
|
||||
end
|
||||
|
||||
@ -24,7 +24,8 @@ class PostRevisionSerializer < ApplicationSerializer
|
||||
:title_changes,
|
||||
:user_changes,
|
||||
:tags_changes,
|
||||
:wiki
|
||||
:wiki,
|
||||
:can_edit
|
||||
|
||||
|
||||
# Creates a field called field_name_changes with previous and
|
||||
@ -100,6 +101,10 @@ class PostRevisionSerializer < ApplicationSerializer
|
||||
object.post.wiki
|
||||
end
|
||||
|
||||
def can_edit
|
||||
scope.can_edit?(object.post)
|
||||
end
|
||||
|
||||
def edit_reason
|
||||
# only show 'edit_reason' when revisions are consecutive
|
||||
current["edit_reason"] if scope.can_view_hidden_post_revisions? ||
|
||||
|
||||
@ -115,6 +115,7 @@ class TopicViewSerializer < ApplicationSerializer
|
||||
result[:can_recover] = true if scope.can_recover_topic?(object.topic)
|
||||
result[:can_remove_allowed_users] = true if scope.can_remove_allowed_users?(object.topic)
|
||||
result[:can_invite_to] = true if scope.can_invite_to?(object.topic)
|
||||
result[:can_invite_via_email] = true if scope.can_invite_via_email?(object.topic)
|
||||
result[:can_create_post] = true if scope.can_create?(Post, object.topic)
|
||||
result[:can_reply_as_new_topic] = true if scope.can_reply_as_new_topic?(object.topic)
|
||||
result[:can_flag_topic] = actions_summary.any? { |a| a[:can_act] }
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<html lang="<%= SiteSetting.default_locale %>">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title><%=SiteSetting.title%></title>
|
||||
<title><%= content_for?(:title) ? yield(:title) + ' - ' + SiteSetting.title : SiteSetting.title %></title>
|
||||
<meta name="description" content="">
|
||||
<%= render partial: "layouts/head" %>
|
||||
<%= render partial: "common/special_font_face" %>
|
||||
|
||||
@ -49,6 +49,13 @@
|
||||
<% end %>
|
||||
<span itemprop='url'><b><a href='<%= @list.more_topics_url %>' rel='next' itemprop='name'><%= t 'next_page' %></a></b></span>
|
||||
</div>
|
||||
|
||||
<% content_for :head do %>
|
||||
<% if params[:page].to_i > 0 %>
|
||||
<link rel="prev" href="<%= @list.prev_topics_url -%>">
|
||||
<% end %>
|
||||
<link rel="next" href="<%= @list.more_topics_url -%>">
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<%- end %>
|
||||
|
||||
@ -4,6 +4,12 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title><%= @topic_view.topic.title %></title>
|
||||
<%= raw crawlable_meta_data(title: @topic_view.title, description: @topic_view.summary, image: @topic_view.image_url, read_time: @topic_view.read_time, like_count: @topic_view.like_count) %>
|
||||
<% if @topic_view.prev_page %>
|
||||
<link rel="prev" href="<%= @topic_view.prev_page_path -%>">
|
||||
<% end %>
|
||||
<% if @topic_view.next_page %>
|
||||
<link rel="next" href="<%= @topic_view.next_page_path -%>">
|
||||
<% end %>
|
||||
</head>
|
||||
<body>
|
||||
<% @topic_view.posts.each do |post| %>
|
||||
|
||||
@ -18,6 +18,23 @@
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% if SiteSetting.tagging_enabled %>
|
||||
<% @tags = @topic_view.topic.tags %>
|
||||
<% if @tags.present? %>
|
||||
<div class='tags-list' itemscope itemtype='http://schema.org/ItemList'>
|
||||
<% @tags.each do |tag| %>
|
||||
<div itemprop='itemListElement' itemscope itemtype='http://schema.org/ListItem'>
|
||||
<meta itemprop='url' content='<%= "#{Discourse.base_url}/tags/#{tag.name}" %>'>
|
||||
<a href='<%= "#{Discourse.base_url}/tags/#{tag.name}" %>' itemprop='item'>
|
||||
<span itemprop='name'><%= tag.name -%></span>
|
||||
</a>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
|
||||
<%= server_plugin_outlet "topic_header" %>
|
||||
|
||||
<hr>
|
||||
@ -25,7 +42,7 @@
|
||||
<%- if include_crawler_content? %>
|
||||
|
||||
<% @topic_view.posts.each do |post| %>
|
||||
<div itemscope itemtype='http://schema.org/Article'>
|
||||
<div itemscope itemtype='http://schema.org/DiscussionForumPosting'>
|
||||
<% if (u = post.user) %>
|
||||
<div class='creator'>
|
||||
<span>
|
||||
@ -63,6 +80,15 @@
|
||||
<% content_for :head do %>
|
||||
<%= auto_discovery_link_tag(@topic_view, {action: :feed, slug: @topic_view.topic.slug, topic_id: @topic_view.topic.id}, title: t('rss_posts_in_topic', topic: @topic_view.title), type: 'application/rss+xml') %>
|
||||
<%= raw crawlable_meta_data(title: @topic_view.title, description: @topic_view.summary, image: @topic_view.image_url, read_time: @topic_view.read_time, like_count: @topic_view.like_count) %>
|
||||
|
||||
<% if @topic_view.prev_page || @topic_view.next_page %>
|
||||
<% if @topic_view.prev_page %>
|
||||
<link rel="prev" href="<%= @topic_view.prev_page_path -%>">
|
||||
<% end %>
|
||||
<% if @topic_view.next_page %>
|
||||
<link rel="next" href="<%= @topic_view.next_page_path -%>">
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% content_for(:title) { "#{@topic_view.page_title}" } %>
|
||||
|
||||
@ -11,59 +11,18 @@
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%if @success%>
|
||||
<p>
|
||||
<%= @success %>
|
||||
<%- if @requires_approval %>
|
||||
<%= t 'login.not_approved' %>
|
||||
<% else %>
|
||||
<br>
|
||||
<br>
|
||||
<a class="btn" href="<%= path "/" %>"><%= t('password_reset.continue', site_name: SiteSetting.title) %></a>
|
||||
<% end %>
|
||||
</p>
|
||||
<% else %>
|
||||
<%if @user.present? %>
|
||||
<h3>
|
||||
<% if @user.has_password? %>
|
||||
<%= t 'password_reset.choose_new' %>
|
||||
<% else %>
|
||||
<%= t 'password_reset.choose' %>
|
||||
<% end %>
|
||||
</h3>
|
||||
|
||||
<%=form_tag({}, method: :put) do %>
|
||||
<p>
|
||||
<span style="display: none;"><input name="username" type="text" value="<%= @user.username %>"></span>
|
||||
<input id="user_password" name="password" size="30" type="password" maxlength="<%= User.max_password_length %>" onkeypress="capsLock(event)">
|
||||
<label><%= t('js.user.password.instructions', count: @user.admin? ? SiteSetting.min_admin_password_length : SiteSetting.min_password_length) %></label>
|
||||
</p>
|
||||
<div id="capsLockWarning" class="caps-lock-warning" style="visibility:hidden"><i class="fa fa-exclamation-triangle"></i> <%= t 'js.login.caps_lock_warning' %></div>
|
||||
<p>
|
||||
<%=submit_tag( @user.has_password? ? t('password_reset.update') : t('password_reset.save'), class: 'btn')%>
|
||||
</p>
|
||||
<%end%>
|
||||
<%end%>
|
||||
<%end%>
|
||||
</div>
|
||||
|
||||
<% content_for :title do %><%=t "password_reset.title" %><% end %>
|
||||
|
||||
<%- content_for(:no_ember_head) do %>
|
||||
<meta name="referrer" content="never">
|
||||
<%= script "ember_jquery" %>
|
||||
<%= render_google_universal_analytics_code %>
|
||||
<%- end %>
|
||||
|
||||
<script type="text/javascript">
|
||||
document.getElementById('user_password').focus();
|
||||
|
||||
function capsLock(e) {
|
||||
kc = e.keyCode?e.keyCode:e.which;
|
||||
sk = e.shiftKey?e.shiftKey:((kc == 16)?true:false);
|
||||
(((kc >= 65 && kc <= 90) && !sk)||((kc >= 97 && kc <= 122) && sk)) ? document.getElementById('capsLockWarning').style.visibility = 'visible' : document.getElementById('capsLockWarning').style.visibility = 'hidden';
|
||||
}
|
||||
|
||||
$.ajax('<%= path "/users/confirm-email-token/#{params[:token]}" %>', {dataType: 'json'});
|
||||
</script>
|
||||
<%- content_for(:head) do %>
|
||||
<meta name="referrer" content="never">
|
||||
<%- end %>
|
||||
|
||||
<%= render_google_analytics_code %>
|
||||
|
||||
@ -147,3 +147,6 @@ relative_url_root =
|
||||
# this ensures backlog (ability of channels to catch up are capped)
|
||||
# message bus default cap is 1000, we are winding it down to 100
|
||||
message_bus_max_backlog_size = 100
|
||||
|
||||
# must be a 64 byte hex string, anything else will be ignored with a warning
|
||||
secret_key_base =
|
||||
|
||||
@ -4,14 +4,20 @@ end
|
||||
|
||||
Rails::Rack::Logger.class_eval do
|
||||
def call_with_quiet_assets(env)
|
||||
previous_level = Rails.logger.level
|
||||
|
||||
override = false
|
||||
if (env['PATH_INFO'].index("/assets/") == 0) or
|
||||
(env['PATH_INFO'].index("mini-profiler-resources") == 0)
|
||||
Rails.logger.level = Logger::ERROR
|
||||
if ::Logster::Logger === Rails.logger
|
||||
override = true
|
||||
Rails.logger.override_level = Logger::ERROR
|
||||
end
|
||||
end
|
||||
|
||||
call_without_quiet_assets(env).tap do
|
||||
Rails.logger.level = previous_level
|
||||
if override
|
||||
Rails.logger.override_level = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
alias_method_chain :call, :quiet_assets
|
||||
|
||||
@ -1,14 +1,4 @@
|
||||
# We have had lots of config issues with SECRET_TOKEN to avoid this mess we are moving it to redis
|
||||
# if you feel strongly that it does not belong there use ENV['SECRET_TOKEN']
|
||||
#
|
||||
token = ENV['SECRET_TOKEN']
|
||||
unless token
|
||||
token = $redis.get('SECRET_TOKEN')
|
||||
unless token && token.length == 128
|
||||
token = SecureRandom.hex(64)
|
||||
$redis.set('SECRET_TOKEN',token)
|
||||
end
|
||||
end
|
||||
|
||||
Discourse::Application.config.secret_token = token
|
||||
Discourse::Application.config.secret_key_base = token
|
||||
# Not fussed setting secret_token anymore, that is only required for
|
||||
# backwards support of "seamless" upgrade from Rails 3.
|
||||
# Discourse has shipped Rails 3 for a very long time.
|
||||
Discourse::Application.config.secret_key_base = GlobalSetting.safe_secret_key_base
|
||||
|
||||
@ -12,21 +12,24 @@ class SilenceLogger < Rails::Rack::Logger
|
||||
end
|
||||
|
||||
def call(env)
|
||||
prev_level = Rails.logger.level
|
||||
path_info = env[PATH_INFO]
|
||||
override = false
|
||||
|
||||
if env[HTTP_X_SILENCE_LOGGER] ||
|
||||
@opts[:silenced].include?(path_info) ||
|
||||
path_info.start_with?('/logs') ||
|
||||
path_info.start_with?('/user_avatar') ||
|
||||
path_info.start_with?('/letter_avatar')
|
||||
Rails.logger.level = Logger::WARN
|
||||
if ::Logster::Logger === Rails.logger
|
||||
override = true
|
||||
Rails.logger.override_level = Logger::WARN
|
||||
end
|
||||
@app.call(env)
|
||||
else
|
||||
super(env)
|
||||
end
|
||||
ensure
|
||||
Rails.logger.level = prev_level
|
||||
Rails.logger.override_level = nil if override
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -1530,11 +1530,8 @@ ar:
|
||||
make_banner: "موضوع دعائي"
|
||||
remove_banner: "إزالة موضوع دعائي"
|
||||
reply:
|
||||
post:
|
||||
title: 'ردّ'
|
||||
topic:
|
||||
title: 'ردّ'
|
||||
help: 'ابدأ بكتابة رد على هذا الموضوع'
|
||||
title: 'ردّ'
|
||||
help: 'ابدأ بكتابة رد على هذا الموضوع'
|
||||
clear_pin:
|
||||
title: "إلغاء التثبيت"
|
||||
help: "إلغاء تثبيت الموضوع حتى لا يظهر في أعلى القائمة"
|
||||
|
||||
@ -104,9 +104,13 @@ bs_BA:
|
||||
google+: 'podijeli link na Google+'
|
||||
email: 'pošalji ovaj link na email'
|
||||
action_codes:
|
||||
public_topic: "postavio ovu temu kao javno %{when}"
|
||||
private_topic: "postavio ovu temu kao privatno %{when}"
|
||||
split_topic: "podjeli ovu temu %{when}"
|
||||
invited_user: "pozvan %{who} %{when}"
|
||||
invited_group: "pozvan %{who} %{when}"
|
||||
removed_user: "uklonjen %{who} %{when}"
|
||||
removed_group: "ukloljen %{who} %{when}"
|
||||
autoclosed:
|
||||
enabled: 'zatvoren %{when}'
|
||||
disabled: 'otvoren %{when}'
|
||||
@ -126,8 +130,24 @@ bs_BA:
|
||||
enabled: 'izlistan %{when}'
|
||||
disabled: 'sklonjen %{when}'
|
||||
topic_admin_menu: "topic admin actions"
|
||||
wizard_required: "Vrijeme je za kofiguraciju vašeg foruma! <a href='%{url}' data-auto-route='true'>Startajte Setup Postavke</a>!"
|
||||
emails_are_disabled: "Sve odlazeće email poruke su globalno onemogućene od strane administratora. Niti jedna notifikacija bilo kakve vrste neće biti poslana."
|
||||
bootstrap_mode_enabled: "Kako bi lakše lansirali svoj novi sajt, trenutno ste u bootstrap modu. Svi novi korisnici će dobiti razinu povjerenja 1 i imati uključen sistematizovani dnevni e-mail pregleda promjena. Naknadno će biti automatski isključeno nakon što ukupan broj korisnika pređe brojku od %{min_users}."
|
||||
bootstrap_mode_disabled: "Bootstrap mod će biti ugašen u sljedećih 24 sata."
|
||||
s3:
|
||||
regions:
|
||||
us_east_1: "SAD Istok (Sjeverna Virdžinija)"
|
||||
us_west_1: "SAD Zapad (Sjeverna Kalifornija)"
|
||||
us_west_2: "SAD Zapad (Oregon)"
|
||||
eu_west_1: "EU (Irska)"
|
||||
eu_central_1: "EU (Frankfurt)"
|
||||
ap_southeast_1: "Azija Pacifik (Singapur)"
|
||||
ap_southeast_2: "Azija Pacifik (Sidnej)"
|
||||
ap_south_1: "Azija Pacifik (Mumai)"
|
||||
ap_northeast_1: "Azija Pacifik (Tokio)"
|
||||
ap_northeast_2: "Azija Pacifik (Seul)"
|
||||
sa_east_1: "Južna Amerika (Sao Paulo)"
|
||||
cn_north_1: "Kina (Peking)"
|
||||
edit: 'izmjeni naslov i kategoriju ove teme'
|
||||
not_implemented: "That feature hasn't been implemented yet, sorry!"
|
||||
no_value: "Ne"
|
||||
@ -189,7 +209,7 @@ bs_BA:
|
||||
like_count: "Broj Lajkova"
|
||||
topic_count: "Broj Tema"
|
||||
post_count: "Broj Postova"
|
||||
user_count: "Broj Članova"
|
||||
user_count: "Korisnici"
|
||||
active_user_count: "Aktivnih korisnika"
|
||||
contact: "Kontaktirajte nas"
|
||||
contact_info: "U slučaju da forum ne radi, molimo kontaktirajte nas na %{contact_info}."
|
||||
@ -233,6 +253,8 @@ bs_BA:
|
||||
undo: "Nazad"
|
||||
revert: "Vrati"
|
||||
failed: "Neuspješno"
|
||||
switch_to_anon: "Uđi u privatni modus"
|
||||
switch_from_anon: "Izađi iz privatnog modusa"
|
||||
banner:
|
||||
close: "Dismiss this banner."
|
||||
edit: "Uredite ovaj baner >>"
|
||||
@ -319,7 +341,7 @@ bs_BA:
|
||||
from: "Od"
|
||||
to: "Za"
|
||||
edit:
|
||||
title: 'Edituj Grupu'
|
||||
title: 'Preimenuj Grupu'
|
||||
full_name: 'Puno ime'
|
||||
add_members: "Dodaj Članove"
|
||||
delete_member_confirm: "Ukloni '%{username}' iz '%{group}' grupe?"
|
||||
@ -327,6 +349,14 @@ bs_BA:
|
||||
title: "Zahtjev za članstvom"
|
||||
body: "Želio bi da apliciram u članstvo @%{groupName}."
|
||||
name_placeholder: "Ime grupe, bez razmaka, ista pravila kao za korisničko ime"
|
||||
public: "Dozvolite korisnicima da se pridruže/napuste grupu slobodno (Zahtjeva da grupa bude vidljiva)"
|
||||
empty:
|
||||
posts: "Ne postoje postovi člana ove grupe."
|
||||
members: "Nema članova u grupi."
|
||||
mentions: "Nema spominjanja u grupi."
|
||||
messages: "Nema novih poruka za ovu grupu."
|
||||
topics: "Nema novih tema od strane članova ove grupe."
|
||||
logs: "Nema novih logova za ovu grupu."
|
||||
add: "Dodaj"
|
||||
join: "Pridruži se grupi"
|
||||
leave: "Napusti grupu"
|
||||
@ -334,14 +364,22 @@ bs_BA:
|
||||
automatic_group: Automatska grupa
|
||||
closed_group: Zatvorena grupa
|
||||
is_group_user: "Vi ste član ove grupe"
|
||||
allow_membership_requests: "Dozvolite korisnicima da šalju zahtjeve za članstvom vlasnicima grupe (Zahtjeva da svako može @spomenuti grupu)"
|
||||
membership: "Članstvo"
|
||||
name: "Ime"
|
||||
user_count: "Broj članova"
|
||||
bio: "O grupi"
|
||||
selector_placeholder: "Dodaj članove"
|
||||
owner: "vlasnik"
|
||||
visible: "Grupa je vidljiva svim korisnicima"
|
||||
index:
|
||||
title: "Grupe"
|
||||
empty: "Vidljive grupe još ne postoje."
|
||||
title:
|
||||
one: "grupa"
|
||||
few: "grupe"
|
||||
other: "grupe"
|
||||
activity: "Aktivnost"
|
||||
members: "Članovi"
|
||||
topics: "Teme"
|
||||
posts: "Postovi"
|
||||
@ -355,11 +393,15 @@ bs_BA:
|
||||
members_mods_and_admins: "Samo članovi grupe, moderatori i admini"
|
||||
everyone: "Svatko"
|
||||
trust_levels:
|
||||
title: "Razina povjerenja je automatski dodijeljena članovima kada su postavljeni: "
|
||||
none: "Ništa"
|
||||
notifications:
|
||||
watching:
|
||||
title: "Posmatram"
|
||||
description: "Dobićete obavijest za svaki novi post u svakoj novoj poruci, i broj novih odgovora će biti prikazan."
|
||||
watching_first_post:
|
||||
title: "Prva objava"
|
||||
description: "Bit će te obavješteni samo o prvim objavama u svakoj novoj temi ove grupe."
|
||||
tracking:
|
||||
title: "Praćenje"
|
||||
description: "Bićete obaviješteni ukoliko neko spomene vaše @ime ili nešto što je naslovljeno za vas, i broj novih odgovora će biti prikazan."
|
||||
@ -369,6 +411,15 @@ bs_BA:
|
||||
muted:
|
||||
title: "Utišano"
|
||||
description: "Nećete biti obaviješteni zbog nove teme unutar ove grupe."
|
||||
flair_url: "Slika Avatara sposobnosti"
|
||||
flair_url_placeholder: "(Opciono) URL slike ili Font Awesome class"
|
||||
flair_bg_color: "Boja pozadine Slike Avatara sposobnosti"
|
||||
flair_bg_color_placeholder: "(Opciono) Hex broj boje"
|
||||
flair_color: "Boja Avatara sposobnosti"
|
||||
flair_color_placeholder: "(Opciono) Hex broj boje"
|
||||
flair_preview_icon: "Preview ikona"
|
||||
flair_preview_image: "Preview slika"
|
||||
flair_note: "Obavještenje: Sposobnosti će biti prikazane samo za korisnike primarne grupe."
|
||||
user_action_groups:
|
||||
'1': "Dati Lajkovi"
|
||||
'2': "Dobijeni Lajkovi"
|
||||
@ -423,6 +474,11 @@ bs_BA:
|
||||
profile: "Profil"
|
||||
mute: "Mutiraj"
|
||||
edit: "Uredi Postavke"
|
||||
download_archive:
|
||||
button_text: "Preuzmite svoju objavu"
|
||||
confirm: "Da li ste sigurni da želite preuzeti svoju objavu?"
|
||||
success: "Preuzimanje je započeto, bit će te obavješteni porukom kada proces bude završen."
|
||||
rate_limit_error: "Objava može biti preuzeta samo jedanput na dan, molimo vas da pokušate sutra ponovo."
|
||||
new_private_message: "Nova poruka"
|
||||
private_message: "Privatne Poruke"
|
||||
private_messages: "Poruke"
|
||||
@ -444,7 +500,9 @@ bs_BA:
|
||||
disable: "Isključi notifikacije"
|
||||
enable: "Uključi notifikacije"
|
||||
each_browser_note: "Napomena: Ovu opciju morate promjeniti na svakom pregledniku."
|
||||
dismiss_notifications: "Odpusti sve"
|
||||
dismiss_notifications_tooltip: "Markiraj sve nepročitane notifikacije kao pročitane"
|
||||
first_notification: "Vaša prva obavijest! Selektirajte je kako bi započeli."
|
||||
disable_jump_reply: "Don't jump to your new post after replying"
|
||||
dynamic_favicon: "Show incoming message notifications on favicon (experimental)"
|
||||
external_links_in_new_tab: "Open all external links in a new tab"
|
||||
@ -458,9 +516,35 @@ bs_BA:
|
||||
suspended_notice: "This user is suspended until {{date}}."
|
||||
suspended_reason: "Reason: "
|
||||
github_profile: "Github"
|
||||
email_activity_summary: "Sažetak aktivnosti"
|
||||
mailing_list_mode:
|
||||
label: "Mejling lista mod"
|
||||
enabled: "Uključite mod Mejling lista"
|
||||
instructions: |
|
||||
Ova Postavka nadvladava postavku Sažetak aktivnosti.<br />
|
||||
Isključene teme (Muted topics) i kategorije nisu uključeni u ovim e-mailovima.
|
||||
daily: "Šalji dnevne promjene."
|
||||
individual: "Šalji e-mail za svaku novu objavu"
|
||||
individual_no_echo: "Šalji e-mail za svaki novu objavu izuzev vlastite"
|
||||
many_per_day: "Pošalji mi e-mail za svaku novu objavu (od prilike {{dailyEmailEstimate}} puta po danu)"
|
||||
few_per_day: "Pošalji mi e-mail za svaku novu objavu (od prilike 2 puta po danu)"
|
||||
tag_settings: "Tagovi"
|
||||
watched_tags: "Gledano"
|
||||
watched_tags_instructions: "Automatski će te gledati sve teme sa ovim tagom. Bit će te obavješteni o svim novim objavama i temama, i također broj novih objava će biti prikazan pored teme."
|
||||
tracked_tags: "Praćeno"
|
||||
tracked_tags_instructions: "Automatski će te pratiti sve teme sa ovim tagovima. Broj novih objava će se pojaviti pored teme."
|
||||
muted_tags: "Isključen"
|
||||
muted_tags_instructions: "Nećete biti obavješteni o novim temama sa ovim tagom, i neće biti prikazani u listi Novije."
|
||||
watched_categories: "Watched"
|
||||
watched_categories_instructions: "Automatski će te gledati sve teme u ovim kategorijama. Bit će te obavješteni o svim novim objavama i temama, i također broj novih objava će biti prikazan pored teme."
|
||||
tracked_categories: "Tracked"
|
||||
tracked_categories_instructions: "Automatski će te pratiti sve teme u ovim kategorijama. Broj novih objava će se pojaviti pored teme."
|
||||
watched_first_post_categories: "Prva objava"
|
||||
watched_first_post_categories_instructions: "Bit će te obavješteni samo o prvim objavama u svakoj novoj temi u ovim kategorijama."
|
||||
watched_first_post_tags: "Prva objava"
|
||||
watched_first_post_tags_instructions: "Bit će te obavješteni o prvoj objavi u svakoj novoj temi sa ovim tagovima."
|
||||
muted_categories: "Muted"
|
||||
muted_categories_instructions: "Nećete biti obavješteni o bilo čemu što se odnosi na nove teme u ovim kategorijama, i neće biti prikazani u listi Novije."
|
||||
delete_account: "Delete My Account"
|
||||
delete_account_confirm: "Are you sure you want to permanently delete your account? This action cannot be undone!"
|
||||
deleted_yourself: "Your account has been deleted successfully."
|
||||
@ -471,7 +555,12 @@ bs_BA:
|
||||
muted_users: "Utišani"
|
||||
muted_users_instructions: "Odbij sve notifikacije od ovih korisnika."
|
||||
muted_topics_link: "Prikaži utišane teme"
|
||||
watched_topics_link: "Prikaži gledane teme"
|
||||
automatically_unpin_topics: "Automatski otkači temu kada dođem do dna"
|
||||
apps: "Aplikacije"
|
||||
revoke_access: "Oduzmi pristup"
|
||||
undo_revoke_access: "Poništi oduzeti pristup"
|
||||
api_approved: "Odobreno:"
|
||||
staff_counters:
|
||||
flags_given: "helpful flags"
|
||||
flagged_posts: "flagged posts"
|
||||
@ -500,6 +589,7 @@ bs_BA:
|
||||
error: "Desila se greška prilikom promjene."
|
||||
change_username:
|
||||
title: "Change Username"
|
||||
confirm: "Ukoliko promijenite vaše korisničko ime, sva dosadašnja citiranja u vašim objavama te @ime spomeni će biti ugašeni/sa vašim eventualno novim nickom razdvojeni. Da li ste APSOLUTNO SIGURNI da to želite učiniti?"
|
||||
taken: "Sorry, that username is taken."
|
||||
error: "There was an error changing your username."
|
||||
invalid: "That username is invalid. It must only include numbers and letters"
|
||||
@ -523,21 +613,25 @@ bs_BA:
|
||||
change_profile_background:
|
||||
title: "Pozadina profila"
|
||||
instructions: "Pozadinske slike profila će biti centrirane i imati širinu od 850px."
|
||||
change_card_background:
|
||||
title: "Pozadina Korisničke kartice"
|
||||
instructions: "Pozadinske slike će biti centrirane i imati standard širinu od 590 pixela."
|
||||
email:
|
||||
title: "Email"
|
||||
instructions: "Nikada se ne pokazuje javno."
|
||||
instructions: "Nikad ne pokazuje javno."
|
||||
ok: "Izgleda dobro. Poslat ćemo email sa konfirmacijom."
|
||||
invalid: "Molimo vas unesite validnu email adresu."
|
||||
authenticated: "Your email has been authenticated by {{provider}}."
|
||||
frequency_immediately: "Slati ćemo vam e-mail obavijesti odmah na novo, ukoliko niste pročitali sadržaj koji smo vam prvobitno e-mailom poslali."
|
||||
name:
|
||||
title: "Ime"
|
||||
instructions: "Vaše puno ime."
|
||||
instructions: "vaše puno ime (opciono)"
|
||||
instructions_required: "Vaše puno ime"
|
||||
too_short: "Vaše ime je prekratko."
|
||||
ok: "Vaše ime izgleda ok."
|
||||
username:
|
||||
title: "Nadimak"
|
||||
instructions: "Originalno, bez razmaka, kratko."
|
||||
instructions: "unikatno, bez tipke praznog prostora, kratko"
|
||||
short_instructions: "Ljudi vas mogu spomenuti preko @{{username}}."
|
||||
available: "Vaš nadimak je dostupan."
|
||||
global_match: "Email već postoji kao član foruma."
|
||||
@ -552,6 +646,7 @@ bs_BA:
|
||||
title: "Interface language"
|
||||
instructions: "User interface language. It will change when you refresh the page."
|
||||
default: "(default)"
|
||||
any: "bilo koji"
|
||||
password_confirmation:
|
||||
title: "Šifra Opet"
|
||||
last_posted: "Posljednji Odgovor"
|
||||
@ -560,25 +655,34 @@ bs_BA:
|
||||
created: "Registrovan"
|
||||
log_out: "Izloguj se"
|
||||
location: "Lokacija"
|
||||
card_badge:
|
||||
title: "Bedž Korisničke kartice"
|
||||
website: "Sajt"
|
||||
email_settings: "Email"
|
||||
like_notification_frequency:
|
||||
title: "Notifikuj ukoliko se nekome sviđa"
|
||||
always: "Uvijek"
|
||||
first_time_and_daily: "Prvi put kada je objava lajkana i svakodnevno"
|
||||
first_time: "Prvi put kada je objava lajkana"
|
||||
never: "Nikad"
|
||||
email_previous_replies:
|
||||
title: "Uključi predhodne odgovore na objave u dnu e-maila"
|
||||
unless_emailed: "ukoliko nije već poslano"
|
||||
always: "uvijek"
|
||||
never: "nikad"
|
||||
email_digests:
|
||||
title: "Kada forum ne posjećujem, pošaljite mi e-mail sa Sažetkom popularnih tema i odgovora"
|
||||
every_30_minutes: "svakih 30. min"
|
||||
every_hour: "po satu"
|
||||
daily: "dnevno"
|
||||
every_three_days: "svaka tri dana"
|
||||
weekly: "nedeljno"
|
||||
every_two_weeks: "svake dvije sedmice"
|
||||
include_tl0_in_digests: "Uključi i sadržaj od strane novih korisnika u e-mail Sažetku"
|
||||
email_in_reply_to: "Uključi odlomake sa odgovorenih objava u e-mailovima"
|
||||
email_direct: "Receive an email when someone quotes you, replies to your post, or mentions your @username"
|
||||
email_private_messages: "Receive an email when someone sends you a private message"
|
||||
email_always: "Pošalji mi e-mail obavijesti čak iako sam aktivan na forumu"
|
||||
other_settings: "Other"
|
||||
categories_settings: "Categories"
|
||||
new_topic_duration:
|
||||
@ -600,6 +704,7 @@ bs_BA:
|
||||
after_4_minutes: "poslije 4 minute"
|
||||
after_5_minutes: "poslije 5 minuta"
|
||||
after_10_minutes: "poslije 10 minuta"
|
||||
notification_level_when_replying: "Kada objavim objavu u temi, postavi tu temu u"
|
||||
invited:
|
||||
search: "kucaj da potražiš pozivnice..."
|
||||
title: "Pozivnice"
|
||||
@ -607,24 +712,33 @@ bs_BA:
|
||||
sent: "poslano"
|
||||
none: "Nema poziva na čekanju"
|
||||
redeemed: "Redeemed Invites"
|
||||
redeemed_tab: "Iskorišteno"
|
||||
redeemed_tab_with_count: "Iskorišteno ({{count}})"
|
||||
redeemed_at: "Redeemed"
|
||||
pending: "Pending Invites"
|
||||
pending_tab: "Na čekanju"
|
||||
pending_tab_with_count: "Na čekanju ({{count}})"
|
||||
topics_entered: "Topics Viewed"
|
||||
posts_read_count: "Posts Read"
|
||||
expired: "This invite has expired."
|
||||
rescind: "Remove"
|
||||
rescinded: "Invite removed"
|
||||
reinvite: "Resend Invite"
|
||||
reinvite_all: "Ponovo pošalji sve pozivnice"
|
||||
reinvited: "Invite re-sent"
|
||||
reinvited_all: "Sve pozivnice su ponovo poslate!"
|
||||
time_read: "Read Time"
|
||||
days_visited: "Days Visited"
|
||||
account_age_days: "Account age in days"
|
||||
create: "Pošalji Pozivnicu"
|
||||
generate_link: "Kopiraj link za invite"
|
||||
link_generated: "Link pozivnice je uspješno generisan!"
|
||||
valid_for: "Link pozvinice je validan jedino za ovu e-mail adresu: %{email}"
|
||||
bulk_invite:
|
||||
none: "Još uvijek niste ovdje pozvali nikoga. Možete slati individualne pozivnice, ili pozvati mnogo ljudi od jednom koristeći se <a href='https://meta.discourse.org/t/send-bulk-invites/16468'>dizanjem CSV datoteke</a>."
|
||||
text: "Bulk Invite from File"
|
||||
success: "File uploaded successfully, you will be notified shortly with progress."
|
||||
error: "Neuspješno, datoteka bi trebala biti u .csv formatu."
|
||||
password:
|
||||
title: "Šifra"
|
||||
too_short: "Vaša šifra je prekratka."
|
||||
@ -632,7 +746,7 @@ bs_BA:
|
||||
same_as_username: "Vaš pasword je isti kao vaše korisničko ime."
|
||||
same_as_email: "Vaš pasword je isti kao vaš email."
|
||||
ok: "Vaša šifra izgleda ok."
|
||||
instructions: "Barem %{count} karaktera."
|
||||
instructions: "minimalno %{count} karaktera"
|
||||
summary:
|
||||
title: "Sumirano"
|
||||
stats: "Statistike"
|
||||
@ -643,6 +757,15 @@ bs_BA:
|
||||
top_topics: "Top Teme"
|
||||
no_topics: "Nema temi još"
|
||||
more_topics: "Više temi"
|
||||
top_badges: "Top bedževi"
|
||||
no_badges: "Još uvijek nema bedževa."
|
||||
more_badges: "Više bedževa"
|
||||
top_links: "Top linkovi"
|
||||
no_links: "Još uvijek nema linkova."
|
||||
most_liked_by: "Najviše lajkano od"
|
||||
most_liked_users: "Najviše lajkano"
|
||||
most_replied_to_users: "Najviše odgovoreno ka"
|
||||
no_likes: "Još uvijek nema lajkova."
|
||||
associated_accounts: "Associated accounts"
|
||||
ip_address:
|
||||
title: "Zadnja IP Adresa"
|
||||
@ -685,8 +808,18 @@ bs_BA:
|
||||
logout: "Izlogovani ste."
|
||||
refresh: "Osvježi"
|
||||
read_only_mode:
|
||||
enabled: "Ovaj sajt je u read only mod-u: Dozvoljeno je čitati. Možete nastaviti sa pregledom, ali odgovaranje na objave, lajkanje i ostale akcije su isključene za sada."
|
||||
login_disabled: "Login is disabled while the site is in read only mode."
|
||||
logout_disabled: "Odjava je isključena sve dok je sajt u read only tj. samo čitanje je dozvoljeno mod-u."
|
||||
too_few_topics_and_posts_notice: "Odpočnimo <a href='http://blog.discourse.org/2014/08/building-a-discourse-community/'>sa diskusijom!</a> Trenutno postoje <strong>%{currentTopics} / %{requiredTopics}</strong> teme i <strong>%{currentPosts} / %{requiredPosts}</strong> objave. Novi posjetioci trebaju par novih diskusija za čitanje i shodne reakcije."
|
||||
too_few_topics_notice: "Odpočnimo <a href='http://blog.discourse.org/2014/08/building-a-discourse-community/'>sa diskusijom!</a> Trenutno postoje <strong>%{currentTopics} / %{requiredTopics}</strong> teme. Novi posjetioci trebaju par novih diskusija za čitanje i shodne reakcije."
|
||||
too_few_posts_notice: "Odpočnimo <a href='http://blog.discourse.org/2014/08/building-a-discourse-community/'>sa diskusijom!</a> Trenutno postoje <strong>%{currentPosts} / %{requiredPosts}</strong> objave. Novi posjetioci trebaju par novih diskusija za čitanje i shodne reakcije."
|
||||
logs_error_rate_notice:
|
||||
reached: "<b>%{relativeAge}</b> – <a href='%{url}' target='_blank'>%{rate}</a> dosegnut postavljeni limit sajta od %{siteSettingRate}."
|
||||
exceeded: "<b>%{relativeAge}</b> – <a href='%{url}' target='_blank'>%{rate}</a> prelazi postavljeni limit sajta od %{siteSettingRate}."
|
||||
learn_more: "learn more..."
|
||||
all_time: 'ukupno'
|
||||
all_time_desc: 'ukupno kreiranih tema'
|
||||
year: 'godina'
|
||||
year_desc: 'teme kreirane u zadnjih 365 dana'
|
||||
month: 'mjesec'
|
||||
@ -703,8 +836,13 @@ bs_BA:
|
||||
sign_up: "Registruj se"
|
||||
hide_session: "Podsjeti me sutra"
|
||||
hide_forever: "ne hvala"
|
||||
hidden_for_session: "OK, pitat ću vas opet sutra. Također možete u svako doba koristiti 'Loguj se' kako bi napravili nalog."
|
||||
intro: "Hej tamo! :heart_eyes: Izgleda da uživaš u ovoj diskusiji, ali još uvijek nemaš prijavljen račun."
|
||||
value_prop: "Kada osnujete nalog, mi pamtimo tačno što ste do sada čitali, tako da uvijek kada se vratite čekat će vas samo nepročitane teme, tačno tamo gdje ste prvobitno stali. Također dobijate i obavijesti, ovdje i preko e-maila, kad god su objavljene nove objave. Također možeš lajkat objave kako bi ste svijetu udijelili svoju velikodušnu ljubav. :heartbeat:"
|
||||
summary:
|
||||
enabled_description: "You're viewing a summary of this topic: the most interesting posts as determined by the community."
|
||||
description: "Trenutno postoje <b>{{replyCount}}</b> odgovora."
|
||||
description_time: "Trenutno postoje <b>{{replyCount}}</b> odgovora sa procijenjenim vremenom čitanja od <b>{{readingTime}} minuta</b>."
|
||||
enable: 'Summarize This Topic'
|
||||
disable: 'Show All Posts'
|
||||
deleted_filter:
|
||||
@ -716,6 +854,7 @@ bs_BA:
|
||||
title: "Privatna Poruka"
|
||||
invite: "Pozovi Druge..."
|
||||
remove_allowed_user: "Do you really want to remove {{name}} from this private message?"
|
||||
remove_allowed_group: "Da li zaista želite da uklonite {{name}} sa ove poruke?"
|
||||
email: 'Email'
|
||||
username: 'Ime'
|
||||
last_seen: 'Viđen'
|
||||
@ -724,6 +863,7 @@ bs_BA:
|
||||
trust_level: 'Nivo Povjerenja'
|
||||
search_hint: 'ime'
|
||||
create_account:
|
||||
disclaimer: "Registracijom, vi se slažete sa <a href='{{privacy_link}}'>policom o privatnosti</a> i <a href='{{tos_link}}'>uslovima korištenja servisa</a>."
|
||||
title: "Kreiraj Nalog"
|
||||
failed: "Something went wrong, perhaps this email is already registered, try the forgot password link"
|
||||
forgot_password:
|
||||
@ -755,6 +895,7 @@ bs_BA:
|
||||
requires_invite: "Sorry, access to this forum is by invite only."
|
||||
not_activated: "You can't log in yet. We previously sent an activation email to you at <b>{{sentTo}}</b>. Please follow the instructions in that email to activate your account."
|
||||
not_allowed_from_ip_address: "You can't login from that IP address."
|
||||
admin_not_allowed_from_ip_address: "Ne možete se logirati kao admin sa te IP adrese."
|
||||
resend_activation_email: "Click here to send the activation email again."
|
||||
sent_activation_email_again: "We sent another activation email to you at <b>{{currentEmail}}</b>. It might take a few minutes for it to arrive; be sure to check your spam folder."
|
||||
to_continue: "Molimo vas ulogujte se"
|
||||
@ -771,6 +912,7 @@ bs_BA:
|
||||
message: "Identifikujemo se sa Twitterom (nadamo se da su vam isključeni popup blokeri)"
|
||||
instagram:
|
||||
title: "sa Instagramom"
|
||||
message: "Prijava preko Instagrama (osigurajte da pop up blokeri budu isključeni)"
|
||||
facebook:
|
||||
title: "sa Facebook"
|
||||
message: "Identifikujemo sa Facebook (nadamo se da su vam isključeni popup blokeri)"
|
||||
@ -780,23 +922,46 @@ bs_BA:
|
||||
github:
|
||||
title: "sa GitHub"
|
||||
message: "Authenticating with GitHub (make sure pop up blockers are not enabled)"
|
||||
emoji_set:
|
||||
apple_international: "Apple/International"
|
||||
google: "Google"
|
||||
twitter: "Twitter"
|
||||
emoji_one: "Emoji One"
|
||||
win10: "Win10"
|
||||
category_page_style:
|
||||
categories_only: "Samo kategorije"
|
||||
categories_with_featured_topics: "Kategorije sa Izdvojenim temama"
|
||||
categories_and_latest_topics: "Kategorije i Novije teme"
|
||||
shortcut_modifier_key:
|
||||
shift: 'Shift'
|
||||
ctrl: 'Ctrl'
|
||||
alt: 'Alt'
|
||||
composer:
|
||||
emoji: "Emotikoni :)"
|
||||
more_emoji: "više..."
|
||||
options: "Opcije"
|
||||
whisper: "šapat"
|
||||
unlist: "nelistan"
|
||||
add_warning: "Ovo je zvanično upozorenje."
|
||||
toggle_whisper: "Uključi kao Whisper"
|
||||
toggle_unlisted: "Uključi kao nelistan"
|
||||
posting_not_on_topic: "Na koju temu želite da odgovorite?"
|
||||
saving_draft_tip: "čuvam"
|
||||
saved_draft_tip: "sačuvano"
|
||||
saved_local_draft_tip: "sačuvano lokalno"
|
||||
similar_topics: "Tvoja tema je slična..."
|
||||
drafts_offline: "offline sačuvano"
|
||||
cannot_see_mention:
|
||||
category: "Spomenuli ste {{username}} ali isti neće biti obavješteni zbog toga što nemaju pristup ovoj kategoriji. Morate ih dodati u Grupu koja ima pristup ka ovoj kategoriji."
|
||||
private: "Spomenuli ste {{username}} ali isti neće biti obaviješteni zbog toga što nisu u mogućnosti da vide ovu personalnu poruku. Morate ih prvobitno pozvati u ovu PP tj. Personalnu poruku."
|
||||
duplicate_link: "Izgleda da je vaš link ka <b>{{domain}}</b> već objavljen u temi od strane <b>@{{username}}</b> u <a href='{{post_url}}'>odgovoru {{ago}}</a> – da li ste sigurni da želite isti ponovo objaviti?"
|
||||
error:
|
||||
title_missing: "Naslov je obavezan"
|
||||
title_too_short: "Naslov mora biti najmanje {{min}} karaktera"
|
||||
title_too_long: "Naslov ne može biti više od {{max}} karaktera"
|
||||
post_missing: "Odgovor ne može biti prazan"
|
||||
post_length: "Odgovor mora biti najmanje {{min}} karaktera"
|
||||
try_like: 'Jeste li probali <i class="fa fa-heart"></i> dugme?'
|
||||
category_missing: "Morate odabrati kategoriju"
|
||||
save_edit: "Sačuvaj Izmene"
|
||||
reply_original: "Odgovori na Originalnu Temu"
|
||||
@ -808,8 +973,10 @@ bs_BA:
|
||||
title: "Ili pritisni Ctrl+Enter"
|
||||
users_placeholder: "Dodaj člana"
|
||||
title_placeholder: "O čemu je ova diskusija u jednoj rečenici?"
|
||||
title_or_link_placeholder: "Ukucajte naziv, ili zalijepite link ovdje"
|
||||
edit_reason_placeholder: "zašto pravite izmjenu?"
|
||||
show_edit_reason: "(dodaj razlog izmjene)"
|
||||
topic_featured_link_placeholder: "Unesite link prikazan sa nazivom"
|
||||
reply_placeholder: "Ovdje kucate vaš tekst. Koristite Markdown, BBcode ili HTML kako bi formatirali isti. Povucite ili zaljepite slike."
|
||||
view_new_post: "Pogledaj svoj novi post."
|
||||
saving: "Učitavam"
|
||||
@ -831,6 +998,7 @@ bs_BA:
|
||||
quote_text: "citat u bloku"
|
||||
code_title: "Formatiran Tekst"
|
||||
code_text: "indent preformatted text by 4 spaces"
|
||||
paste_code_text: "ukucaj ili zalijepi kod ovdje"
|
||||
upload_title: "Upload"
|
||||
upload_description: "unesi opis uploada"
|
||||
olist_title: "Numbered List"
|
||||
@ -842,6 +1010,10 @@ bs_BA:
|
||||
help: "Markdown Editing Help"
|
||||
toggler: "sakrij ili pokaži komposer"
|
||||
modal_cancel: "Otkaži"
|
||||
cant_send_pm: "Neuspješno, ne možete slati poruke ka %{username}."
|
||||
yourself_confirm:
|
||||
title: "Da li ste zaboravili da dodate primaoca?"
|
||||
body: "Trenutno ova poruka biješe poslana samo vama!"
|
||||
admin_options_title: "Optional staff settings for this topic"
|
||||
auto_close:
|
||||
label: "Auto-close topic time:"
|
||||
@ -855,6 +1027,7 @@ bs_BA:
|
||||
notifications:
|
||||
title: "obaviještenja na spomenuti @nadimak, odgovori na vaše teme i postove, privatne poruke, itd"
|
||||
none: "Nemate obavijesti trenutno."
|
||||
empty: "Nema obavještenja."
|
||||
more: "pogledaj starija obaviještenja"
|
||||
total_flagged: "ukupno opomenutih postova"
|
||||
mentioned: "<i title='spomenut' class='icon'>@</i><p><span>{{username}}</span> {{description}}</p>"
|
||||
@ -867,22 +1040,41 @@ bs_BA:
|
||||
invitee_accepted: "<i title='prihvatio pozivnicu' class='fa fa-user'></i><p><span>{{username}}</span> accepted your invitation</p>"
|
||||
moved_post: "<i title='pomjerio post' class='fa fa-sign-out'></i><p><span>{{username}}</span> moved {{description}}</p>"
|
||||
granted_badge: "<i title='bedž dobijen' class='fa fa-certificate'></i><p>Zaslužen '{{description}}'</p>"
|
||||
watching_first_post: "<i title='new topic' class='fa fa-dot-circle-o'></i><p><span>Nova Tema</span> {{description}}</p>"
|
||||
alt:
|
||||
mentioned: "Spomenut od"
|
||||
quoted: "Citiran od"
|
||||
replied: "Odgovoreno"
|
||||
posted: "Post od"
|
||||
edited: "Editujte vaš post"
|
||||
liked: "Vole vaš post"
|
||||
private_message: "Privatna poruka od"
|
||||
invited_to_private_message: "Pozvani na privatnu poruku od "
|
||||
invited_to_topic: "Pozvani na temu od"
|
||||
invitee_accepted: "Pozivnica prihvaćena od"
|
||||
moved_post: "Vaša objava je premještena od strane "
|
||||
linked: "Link ka vašoj objavi"
|
||||
granted_badge: "Bedž odobren"
|
||||
group_message_summary: "Poruke u grupnom sandučetu"
|
||||
popup:
|
||||
mentioned: '{{username}} vas je spomenuo/la u "{{topic}}" - {{site_title}}'
|
||||
group_mentioned: '{{username}} vas je spomenuo/la u "{{topic}}" - {{site_title}}'
|
||||
quoted: '{{username}} vas je citirao/la u "{{topic}}" - {{site_title}}'
|
||||
replied: '{{username}} vam je odgovorio/la u "{{topic}}" - {{site_title}}'
|
||||
posted: '{{username}} je objavio/la "{{topic}}" - {{site_title}}'
|
||||
private_message: '{{username}} vam je poslao/la privatnu poruku u "{{topic}}" - {{site_title}}'
|
||||
linked: '{{username}} je linkao/la vašu objavu "{{topic}}" - {{site_title}}'
|
||||
upload_selector:
|
||||
title: "Dodaj sliku"
|
||||
title_with_attachments: "Dodaj sliku ili fajl"
|
||||
from_my_computer: "Sa mog uređaja"
|
||||
from_the_web: "Sa neta"
|
||||
remote_tip: "link do slike http://primjer.com/slika.jpg"
|
||||
remote_tip_with_attachments: "link ka slici ili datoteci {{authorized_extensions}}"
|
||||
local_tip: "Izaberi slike sa svog uređaja"
|
||||
local_tip_with_attachments: "izaberite slike ili fajlove sa vašeg uređaja {{authorized_extensions}}"
|
||||
hint: "(možete i mišom prenijeti vaše slike direktno iz vašeg foldera ovdje)"
|
||||
hint_for_supported_browsers: "također možete povući i ispustiti ili zalijepiti slike u editor teksta"
|
||||
uploading: "Uplodujem"
|
||||
select_file: "Izaberi fajl"
|
||||
image_link: "link do vaše slike će pokazivati"
|
||||
@ -891,8 +1083,10 @@ bs_BA:
|
||||
relevance: "Bitnost"
|
||||
latest_post: "Zadnji postovi"
|
||||
most_viewed: "Najviše pregledano"
|
||||
most_liked: "Najviše lajkan"
|
||||
select_all: "Izaberi sve"
|
||||
clear_all: "Izbriši sve"
|
||||
too_short: "Vaš termin za pretragu je prekratak."
|
||||
title: "traži teme, postove, članove ili kategorije"
|
||||
no_results: "Nema rezultata."
|
||||
no_more_results: "Nema rezultata pretrage."
|
||||
@ -900,16 +1094,65 @@ bs_BA:
|
||||
post_format: "#{{post_number}} od {{username}}"
|
||||
context:
|
||||
user: "Traži postove od @{{username}}"
|
||||
category: "Traži #{{category}} kategoriju"
|
||||
topic: "Pretraži ovu temu"
|
||||
private_messages: "Pretraži poruke"
|
||||
advanced:
|
||||
title: Napredna tražilica
|
||||
posted_by:
|
||||
label: Objavljeno od
|
||||
in_category:
|
||||
label: U kategoriji
|
||||
in_group:
|
||||
label: U grupi
|
||||
with_badge:
|
||||
label: Sa bedžom
|
||||
with_tags:
|
||||
label: Sa tagovima
|
||||
filters:
|
||||
label: Izlistaj samo teme/objave koje...
|
||||
likes: Moji lajkovi
|
||||
posted: Moje objave
|
||||
watching: Pratim
|
||||
tracking: Pratim
|
||||
private: su u mojim porukama
|
||||
bookmarks: Boji bookmark-ci
|
||||
first: su friške prve objave
|
||||
pinned: su okačene
|
||||
unpinned: nisu okačene
|
||||
wiki: su wiki
|
||||
statuses:
|
||||
label: Gdje teme
|
||||
open: su otvorene
|
||||
closed: su zatvorene
|
||||
archived: su arhivirane
|
||||
noreplies: imaju nula odgovora
|
||||
single_user: sadrži jednog korisnika
|
||||
post:
|
||||
count:
|
||||
label: Minimalan broj objava
|
||||
time:
|
||||
label: Objavljeno
|
||||
before: prije
|
||||
after: poslije
|
||||
hamburger_menu: "idi ka drugoj temi, listi ili kategoriji"
|
||||
new_item: "novo"
|
||||
go_back: 'go back'
|
||||
not_logged_in_user: 'user page with summary of current activity and preferences'
|
||||
current_user: 'go to your user page'
|
||||
topics:
|
||||
new_messages_marker: "zadnja posjeta"
|
||||
bulk:
|
||||
select_all: "Označi sve"
|
||||
clear_all: "Očisti sve"
|
||||
unlist_topics: "Skini teme sa liste"
|
||||
reset_read: "Reset Read"
|
||||
delete: "Delete Topics"
|
||||
dismiss: "Odbaci"
|
||||
dismiss_read: "Odbaci sve nepročitane"
|
||||
dismiss_button: "Odbaci..."
|
||||
dismiss_tooltip: "Odbaci samo nove objave ili stopiraj praćenje tema"
|
||||
also_dismiss_topics: "Prestani pratiti ove teme tako da se ubuduće za mene nikad ne prikazuju kao nepročitane "
|
||||
dismiss_new: "Dismiss New"
|
||||
toggle: "toggle bulk selection of topics"
|
||||
actions: "Bulk Actions"
|
||||
@ -918,6 +1161,9 @@ bs_BA:
|
||||
archive_topics: "Archive Topics"
|
||||
notification_level: "Change Notification Level"
|
||||
choose_new_category: "Izaberi novu kategoriju za temu:"
|
||||
change_tags: "Izmijeni tagove"
|
||||
choose_new_tags: "Odaberi nove tagove za ove teme:"
|
||||
changed_tags: "Tagovi ovih tema su izmijenjeni."
|
||||
none:
|
||||
unread: "Nemate više nepročitanih tema."
|
||||
new: "Nemate više novih tema."
|
||||
@ -925,9 +1171,13 @@ bs_BA:
|
||||
posted: "Niste odgovorili ni na jednu temu."
|
||||
latest: "Nema više novih tema. To je tužno."
|
||||
hot: "Nema popularnih tema."
|
||||
bookmarks: "Nemate još bookmark-iranih tema."
|
||||
category: "Nema više tema u {{category}}."
|
||||
top: "Nema više popularnih tema."
|
||||
search: "Nema rezultata pretrage"
|
||||
educate:
|
||||
new: '<p>Vaše nove teme se ovdje pojavljuju.</p><p>Načelno, teme se smatraju novim i prikazivat će<span class="badge new-topic badge-notification" style="vertical-align:middle;line-height:inherit;">nova</span> indikator u slučaju da su objavljena u zadnja 2 dana.</p><p>Posjetite svoje <a href="%{userPrefsUrl}">postavke</a> ukoliko želite da to izmijenite.</p>'
|
||||
unread: '<p>Vaše nepročitane teme se ovdje pojavljuju.</p><p>Načelno, teme su smatrane nepročitanim i prikazivat će brojač nepročitanih poruka<span class="badge new-posts badge-notification">1</span> ukoliko ste:</p><ul><li>Kreirali temu</li><li>Odgovorili na temu</li><li>Čitali temu duže od 4 minuta</li></ul><p>Ili ako ste explicitno označili temu za Praćenje ili Posmatrane preko kontrole obavještenja na dnu svake od tema.</p><p>Posjetite vaše <a href="%{userPrefsUrl}">postavke</a> ukoliko želite da to izmijenite.</p>'
|
||||
bottom:
|
||||
latest: "Nema više novih tema."
|
||||
hot: "Nema više popularnih tema."
|
||||
@ -937,10 +1187,21 @@ bs_BA:
|
||||
unread: "Nema više nepročitanih tema."
|
||||
category: "Nema više tema na kategoriji {{category}}."
|
||||
top: "Nema više popularnih tema."
|
||||
bookmarks: "Nema više bookmark-ovanih tema."
|
||||
search: "Nema više rezultata pretrage."
|
||||
topic:
|
||||
unsubscribe:
|
||||
stop_notifications: "Sad će te dobijati manje obavještenja za <strong>{{title}}</strong>"
|
||||
change_notification_state: "Vaše trenutno stanje obavještenja je"
|
||||
create: 'Započni Temu'
|
||||
create_long: 'Započni novu Temu'
|
||||
private_message: 'Započni privatnu konverzaciju'
|
||||
archive_message:
|
||||
help: 'Premjesti poruke u vašu arhivu'
|
||||
title: 'Arhiva'
|
||||
move_to_inbox:
|
||||
title: 'Premjesti u Sanduče'
|
||||
help: 'Premjesti poruke nazad u Sanduče'
|
||||
list: 'Teme'
|
||||
new: 'nova tema'
|
||||
unread: 'nepročitana'
|
||||
@ -973,16 +1234,27 @@ bs_BA:
|
||||
auto_close_title: 'Auto-Close Settings'
|
||||
auto_close_save: "Sačuvaj"
|
||||
auto_close_remove: "Don't Auto-Close This Topic"
|
||||
timeline:
|
||||
back: "Nazad"
|
||||
back_description: "Vratite se nazad na vašu zadnju nepročitanu objavu"
|
||||
replies_short: "%{current} / %{total}"
|
||||
progress:
|
||||
title: progres teme
|
||||
go_top: "vrh"
|
||||
go_bottom: "dno"
|
||||
go: "idi"
|
||||
jump_bottom: "skoči na zadnju objavu"
|
||||
jump_prompt: "skoči na..."
|
||||
jump_prompt_of: "od %{count} objava"
|
||||
jump_prompt_long: "Na koju objavu želite skočiti?"
|
||||
jump_bottom_with_number: "skoči na post %{post_number}"
|
||||
total: ukupan broj
|
||||
current: trenutni post
|
||||
notifications:
|
||||
title: izmijenite učestalost dobijanja obavještenja o ovoj temi
|
||||
reasons:
|
||||
mailing_list_mode: "Imate uključenu mail listu, stoga će te biti obavještavani o odgovorima na ovu temu preko e-maila."
|
||||
'3_10': 'Dobijat će te obavijesti jer pratite tag na ovoj temi.'
|
||||
'3_6': 'Dobijat ćete notifikacije zato što motrite ovu temu.'
|
||||
'3_5': 'Dobijat ćete notifikacije zato što motrite temu automatski.'
|
||||
'3_2': 'Dobijat ćete notifikacije zato što pratite ovu temu.'
|
||||
@ -999,12 +1271,16 @@ bs_BA:
|
||||
'0': 'Ignorišete sve notifikacije u ovoj temi.'
|
||||
watching_pm:
|
||||
title: "Motrenje"
|
||||
description: "Bit ćete obavješteni o svakom novom odgovoru u ovoj poruci, te će biti prikazan broj novih odgovora."
|
||||
watching:
|
||||
title: "Motrenje"
|
||||
description: "Bit će te obavješteni o svakom novom odgovoru na ovu temu, te će biti prikazan broj novih odgovora."
|
||||
tracking_pm:
|
||||
title: "Praćenje"
|
||||
description: "Broj novih odgovora će biti prikazan za ovu poruku. Bit će te obavješteni ukoliko neko pomene vaše @ime ili vam odgovori na poruku."
|
||||
tracking:
|
||||
title: "Praćenje"
|
||||
description: "Broj novih odgovora će biti prikazan za ovu temu. Bit će te obavješteni ukoliko neko pomene vaše @ime ili vam odgovori na temu."
|
||||
regular:
|
||||
title: "Regularan"
|
||||
description: "Dobiti ćete notifikaciju kada neko spomene tvoje @name ili odgovori na tvoj post."
|
||||
@ -1016,6 +1292,7 @@ bs_BA:
|
||||
description: "You will never be notified of anything about this private message."
|
||||
muted:
|
||||
title: "Mutirano"
|
||||
description: "Nećete biti nikad obavješteni o bilo čemu sa ove teme, i neće biti prikazana u Novije"
|
||||
actions:
|
||||
recover: "Un-Delete Topic"
|
||||
delete: "Delete Topic"
|
||||
@ -1030,39 +1307,79 @@ bs_BA:
|
||||
invisible: "Make Unlisted"
|
||||
visible: "Make Listed"
|
||||
reset_read: "Reset Read Data"
|
||||
make_public: "Napiši temu javno"
|
||||
make_private: "Napiši privatnu poruku"
|
||||
feature:
|
||||
pin: "Prikači temu"
|
||||
unpin: "Otkači temu"
|
||||
pin_globally: "Okači temu globalno"
|
||||
make_banner: "Banner tema"
|
||||
remove_banner: "Odstrani Banner temu"
|
||||
reply:
|
||||
title: 'Odgovori'
|
||||
help: 'počni sa pisanjem odgovora na ovu temu'
|
||||
post:
|
||||
title: 'Odgovori'
|
||||
topic:
|
||||
title: 'Odgovori'
|
||||
help: 'odpočni odgovor na ovu temu'
|
||||
clear_pin:
|
||||
title: "Clear pin"
|
||||
help: "Clear the pinned status of this topic so it no longer appears at the top of your topic list"
|
||||
share:
|
||||
title: 'Sheruj'
|
||||
help: 'podjeli link do ove teme'
|
||||
print:
|
||||
title: 'Print'
|
||||
help: 'Otvori printersku verziju ove teme'
|
||||
flag_topic:
|
||||
title: 'Opomena'
|
||||
help: 'anonimno prijavi ovu temu ili pošalji privatnu notifikaciju'
|
||||
success_message: 'Uspješno ste opomenuli ovu temu.'
|
||||
feature_topic:
|
||||
title: "Istakni ovu temu."
|
||||
pin: "Postavi ovu temu da se pojavljuje na vrhu {{categoryLink}} kategorije sve dok"
|
||||
confirm_pin: "Već imate {{count}} okačenih tema. Previše okačenih tema može praviti teret za nove i anonimne korisnike. Da li ste sigurni da želite okačiti još jednu temu u ovoj kategoriji?"
|
||||
unpin: "Uklonite ovu temu sa vrha {{categoryLink}} kategorije."
|
||||
unpin_until: "Uklonite ovu temu sa vrha {{categoryLink}} kategorije ili sačekajte do <strong>%{until}</strong>."
|
||||
pin_note: "Korisnici mogu sami individualno za sebe odkloniti okačku sa teme."
|
||||
pin_validation: "Potreban je datum kako bi okačili ovu temu."
|
||||
not_pinned: "Nema okačenih tema u {{categoryLink}}."
|
||||
pin_globally: "Postavi ovu temu da se prikazuje na vrhu svih lista tema sve do"
|
||||
confirm_pin_globally: "Već imate {{count}} globalno okačene teme. Previše okačenih tema mogu praviti teret za nove i anonimne korisnike. Da li ste sigurni da želite okačiti još jednu temu u ovoj kategoriji?"
|
||||
unpin_globally: "Uklonite ovu temu sa vrha svih lista tema."
|
||||
unpin_globally_until: "Odklonite ovu temu sa vrha svih lista tema ili sačekajte do <strong>%{until}</strong>."
|
||||
global_pin_note: "Korisnici mogu sami individualno za sebe ukloniti okačku sa teme."
|
||||
not_pinned_globally: "Nema tema okačenih globalno."
|
||||
make_banner: "Postavi ovu temu kao banner koji se pojavljuje na vrhu svih stranica."
|
||||
remove_banner: "Uklonite banner koji se pojavljuje u vrhu svih stranica."
|
||||
banner_note: "Korisnici mogu odkloniti banner tako što će ga zatvoriti. U svakom momentu samo jedna tema može biti postavljena za banner."
|
||||
no_banner_exists: "Nema banner tema."
|
||||
banner_exists: "Trenutno <strong class='badge badge-notification unread'>postoji</strong> banner tema."
|
||||
inviting: "Inviting..."
|
||||
automatically_add_to_groups: "Ova pozivnica uključuje također i pristup ka sljedećim grupama:"
|
||||
invite_private:
|
||||
title: 'Invite to Private Message'
|
||||
email_or_username: "Invitee's Email or Username"
|
||||
email_or_username_placeholder: "email address or username"
|
||||
action: "Invite"
|
||||
success: "We've invited that user to participate in this private message."
|
||||
success_group: "Pozvali ste čitavu tu grupu da učestvuje u raspavi u ovoj poruci."
|
||||
error: "Sorry, there was an error inviting that user."
|
||||
group_name: "group name"
|
||||
controls: "Kontrole teme"
|
||||
invite_reply:
|
||||
title: 'Pozivnica'
|
||||
username_placeholder: "korisničko ime"
|
||||
action: 'Email pozivnica'
|
||||
help: 'pošalji pozivnicu svojim prijateljima tako da i oni mogu odgovoriti na ovu temu. Bey registracije.'
|
||||
to_forum: "We'll send a brief email allowing your friend to immediately join by clicking a link, no login required."
|
||||
sso_enabled: "Unesite korisničko ime osobe koju želite da pozovete u ovu temu."
|
||||
to_topic_blank: "Unesite korisničko ime ili e-mail adresu osobe koju želite da pozovete u ovu temu."
|
||||
to_topic_email: "Unijeli ste e-mail adresu. Poslat ćemo e-mailom pozivnicu koja će omogućiti vašem prijatelju da odmah odgovori na ovu temu."
|
||||
to_topic_username: "Unijeli ste korisničko ime. Na isto ćemo poslati obavještenje sa linkom pozivnice na ovu temu."
|
||||
to_username: "Unesite korisničko ime osobe koju želite pozvati. Poslati ćemo obavještenje sa linkom pozivnice na ovu temu."
|
||||
email_placeholder: 'name@example.com'
|
||||
success_email: "Poslali smo e-mailom pozivnicu ka <b>{{emailOrUsername}}</b>. Obavjestiti ćemo vas kada pozivnica bude iskorištena. Provjerite tab pozivnica na vašoj profilnoj stranici kako bi ste upratili sve vaše pozivnice."
|
||||
success_username: "Pozvali smo tog korisnika da prisustvuje u ovoj temi."
|
||||
error: "Sorry, we couldn't invite that person. Perhaps they are already a user?"
|
||||
login_reply: 'Uloguj se da odgovoriš'
|
||||
filters:
|
||||
@ -1108,6 +1425,7 @@ bs_BA:
|
||||
edit: "Sorry, there was an error editing your post. Please try again."
|
||||
upload: "Sorry, there was an error uploading that file. Please try again."
|
||||
too_many_uploads: "Sorry, you can only upload one file at a time."
|
||||
too_many_dragged_and_dropped_files: "Žao nam je, možete dizati samo 10 slika odjednom."
|
||||
image_upload_not_allowed_for_new_user: "Sorry, new users can not upload images."
|
||||
attachment_upload_not_allowed_for_new_user: "Sorry, new users can not upload attachments."
|
||||
attachment_download_requires_login: "Sorry, you need to be logged in to download attachments."
|
||||
@ -1329,6 +1647,8 @@ bs_BA:
|
||||
top:
|
||||
title: "Popularne"
|
||||
help: "najaktivnije teme u zadnjih godinu, mjesec, sedmicu i dan"
|
||||
all:
|
||||
title: "Sve vrijeme"
|
||||
yearly:
|
||||
title: "Popularne Godišnje"
|
||||
monthly:
|
||||
@ -1337,12 +1657,15 @@ bs_BA:
|
||||
title: "Popularne Sedmično"
|
||||
daily:
|
||||
title: "Popularne Dnevno"
|
||||
all_time: "Sve vrijeme"
|
||||
today: "Danas"
|
||||
browser_update: 'Nažalost, vaš internet browser je prestar za ovaj korišćenje ovog foruma</a>. Idite na i <a href="http://browsehappy.com">obnovite vaš browser</a>.'
|
||||
permission_types:
|
||||
full: "Kreiraj / Odgovori / Vidi"
|
||||
create_post: "Odgovori / Vidi"
|
||||
readonly: "Vidi"
|
||||
badges:
|
||||
multiple_grant: "nagrađen više puta"
|
||||
admin_js:
|
||||
type_to_filter: "kucaj da sortiraš..."
|
||||
admin:
|
||||
@ -1462,6 +1785,9 @@ bs_BA:
|
||||
info_html: "Your API key will allow you to create and update topics using JSON calls."
|
||||
all_users: "All Users"
|
||||
note_html: "Keep this key <strong>secret</strong>, all users that have it may create arbitrary posts as any user."
|
||||
web_hooks:
|
||||
events:
|
||||
completion: "Vrijeme završetka"
|
||||
plugins:
|
||||
title: "Pluginovi"
|
||||
installed: "Instalirani pluginovi"
|
||||
@ -1957,11 +2283,31 @@ bs_BA:
|
||||
with_time: <span class="username">%{username}</span> at <span class="time">%{time}</span>
|
||||
emoji:
|
||||
add: "Dodaj novi emoji"
|
||||
embedding:
|
||||
embed_whitelist_selector: "CSS selector za elemente koji su dozvoljeni u embeds"
|
||||
embed_blacklist_selector: "CSS selector za elemente koji su odstranjeni sa embeds"
|
||||
embed_classname_whitelist: "Dopuštena CSS class imena"
|
||||
feed_polling_enabled: "Ubaci objave preko RSS/ATOM"
|
||||
feed_polling_url: "URL ili RSS/ATOM feed za crawl"
|
||||
save: "Sačuvaj Embedding postavke"
|
||||
permalink:
|
||||
title: "Permalink-ovi"
|
||||
url: "URL"
|
||||
topic_id: "ID teme"
|
||||
topic_title: "Tema"
|
||||
post_id: "ID objave"
|
||||
post_title: "Objava"
|
||||
category_id: "ID kategorije"
|
||||
category_title: "Kategorija"
|
||||
external_url: "Vanjski URL"
|
||||
delete_confirm: Jeste li sigurni da želite izbrisati ovaj permalink?
|
||||
form:
|
||||
label: "Novo:"
|
||||
add: "Dodaj"
|
||||
filter: "Pretraga (URL ili vanjski URL)"
|
||||
wizard_js:
|
||||
wizard:
|
||||
done: "Urađeno"
|
||||
back: "Prethodno"
|
||||
next: "Iduće"
|
||||
step: "%{current} od %{total}"
|
||||
@ -1974,6 +2320,7 @@ bs_BA:
|
||||
other: "Vaša zajednica ima %{count} članova osoblja."
|
||||
invites:
|
||||
add_user: "Dodaj"
|
||||
none_added: "Niste pozvali ni jednog admina/moderatora. Jeste li sigurni da želite nastaviti?"
|
||||
roles:
|
||||
admin: "Admin"
|
||||
moderator: "Moderator"
|
||||
|
||||
@ -154,6 +154,7 @@ cs:
|
||||
enabled: 'uvedeno %{when}'
|
||||
disabled: 'neuvedeno %{when}'
|
||||
topic_admin_menu: "akce administrátora tématu"
|
||||
wizard_required: "Je čas nastavit vaše fórum! <a href='%{url}' data-auto-route='true'>Spustit průvodce nastavením</a>!"
|
||||
emails_are_disabled: "Všechny odchozí emaily byly administrátorem vypnuty. Žádné odchozí emaily nebudou odeslány."
|
||||
bootstrap_mode_enabled: "Aby se váš web jednodušeji rozjel, nachází se v režimu bootstrap. Všichni noví uživatelé začínají s důveryhodností 1 a mají povolené denní odesílání souhrnných emailů. Tento režim se automaticky vypne, jakmile počet registrovaných uživatelů překročí %{min_users}."
|
||||
bootstrap_mode_disabled: "Režim bootstrap bude deaktivován v následujících 24 hodinách."
|
||||
@ -233,7 +234,7 @@ cs:
|
||||
like_count: "Líbí se"
|
||||
topic_count: "Témata"
|
||||
post_count: "Příspěvky"
|
||||
user_count: "Noví uživatelé"
|
||||
user_count: "Uživatelé"
|
||||
active_user_count: "Aktivní uživatelé"
|
||||
contact: "Kontaktujte nás"
|
||||
contact_info: "V případě kritické chyby nebo urgentní záležitosti ovlivňující tuto stránku nás prosím kontaktujte na %{contact_info}."
|
||||
@ -346,6 +347,11 @@ cs:
|
||||
one: "1 uživatel"
|
||||
few: "%{count} uživatelé"
|
||||
other: "%{count} uživatelů"
|
||||
group_histories:
|
||||
actions:
|
||||
change_group_setting: "Změnit nastavení skupiny"
|
||||
add_user_to_group: "Přidat uživatele"
|
||||
remove_user_from_group: "Odebrat uživatele"
|
||||
groups:
|
||||
add: "Přidat"
|
||||
selector_placeholder: "Přidat členy"
|
||||
@ -472,6 +478,7 @@ cs:
|
||||
each_browser_note: "Poznámka: Musíš změnit tuto volbu v každém prohlížeči, který používáš."
|
||||
dismiss_notifications: "Odbýt vše"
|
||||
dismiss_notifications_tooltip: "Označit všechny nepřečtené notifikace jako přečtené"
|
||||
first_notification: "Vaše první notifikace! Klikněte zde a začněte."
|
||||
disable_jump_reply: "Po odpovědi nepřeskakovat na nový příspěvek"
|
||||
dynamic_favicon: "Zobrazit počet nových témat v ikoně prohlížeče"
|
||||
external_links_in_new_tab: "Otevírat všechny externí odkazy do nové záložky"
|
||||
@ -977,6 +984,7 @@ cs:
|
||||
title: "Nebo zmáčkněte Ctrl+Enter"
|
||||
users_placeholder: "Přidat uživatele"
|
||||
title_placeholder: "O čem je ve zkratce tato diskuze?"
|
||||
title_or_link_placeholder: "Sem vložte název téma"
|
||||
edit_reason_placeholder: "proč byla nutná úprava?"
|
||||
show_edit_reason: "(přidat důvod úpravy)"
|
||||
reply_placeholder: "Piš tady. Pro formátování používej Markdown, BBCode nebo HTML. Přetáhni nebo vlož obrázky."
|
||||
@ -1371,11 +1379,8 @@ cs:
|
||||
make_banner: "Banner Topic"
|
||||
remove_banner: "Remove Banner Topic"
|
||||
reply:
|
||||
post:
|
||||
title: 'Odpovědět'
|
||||
topic:
|
||||
title: 'Odpovědět'
|
||||
help: 'začněte psát odpověď na toto téma'
|
||||
title: 'Odpovědět'
|
||||
help: 'začněte psát odpověď na toto téma'
|
||||
clear_pin:
|
||||
title: "Odstranit připnutí"
|
||||
help: "Odebere připnutí tohoto tématu, takže se již nebude zobrazovat na vrcholu seznamu témat"
|
||||
|
||||
@ -1276,11 +1276,8 @@ da:
|
||||
make_banner: "Gør emnet til en banner"
|
||||
remove_banner: "Emnet skal ikke være banner længere"
|
||||
reply:
|
||||
post:
|
||||
title: 'Svar'
|
||||
topic:
|
||||
title: 'Svar'
|
||||
help: 'begynd at skrive et svar til dette emne'
|
||||
title: 'Svar'
|
||||
help: 'begynd at skrive et svar til dette emne'
|
||||
clear_pin:
|
||||
title: "Fjern tegnestift"
|
||||
help: "Fjern tegnestiften på dette emne så det ikke længere vises i toppen af emnelisten"
|
||||
|
||||
@ -214,7 +214,7 @@ de:
|
||||
like_count: "Likes"
|
||||
topic_count: "Themen"
|
||||
post_count: "Beiträge"
|
||||
user_count: "Neue Benutzer"
|
||||
user_count: "Benutzer"
|
||||
active_user_count: "Aktive Benutzer"
|
||||
contact: "Kontaktiere uns"
|
||||
contact_info: "Im Falle eines kritischen Problems oder einer dringenden Sache, die diese Website betreffen, kontaktiere uns bitte unter %{contact_info}."
|
||||
@ -1407,7 +1407,6 @@ de:
|
||||
title: 'Antworten'
|
||||
topic:
|
||||
title: 'Antworten'
|
||||
help: 'beginne damit eine Antwort auf dieses Thema zu verfassen'
|
||||
clear_pin:
|
||||
title: "Loslösen"
|
||||
help: "Dieses Thema von der Themenliste loslösen, sodass es nicht mehr am Anfang der Liste steht."
|
||||
@ -1533,6 +1532,7 @@ de:
|
||||
edit: "Du bearbeitest {{link}} {{replyAvatar}} {{username}}"
|
||||
edit_reason: "Grund: "
|
||||
post_number: "Beitrag {{number}}"
|
||||
wiki_last_edited_on: "Wiki zuletzt bearbeitet am"
|
||||
last_edited_on: "Beitrag zuletzt bearbeitet am"
|
||||
reply_as_new_topic: "Mit verknüpftem Thema antworten"
|
||||
continue_discussion: "Fortsetzung der Diskussion von {{postLink}}:"
|
||||
@ -2678,7 +2678,7 @@ de:
|
||||
revoke_admin: "Administration entziehen"
|
||||
grant_moderation: "Moderation gewähren"
|
||||
revoke_moderation: "Moderation entziehen"
|
||||
backup_operation: "Backup läuft"
|
||||
backup_create: "Backup erstellen"
|
||||
deleted_tag: "Schlagwort gelöscht"
|
||||
renamed_tag: "Schlagwort umbenannt"
|
||||
revoke_email: "E-Mail widerrufen"
|
||||
@ -2687,6 +2687,7 @@ de:
|
||||
activate_user: "Benutzer aktivieren"
|
||||
deactivate_user: "Benutzer deaktivieren"
|
||||
change_readonly_mode: "Nur-Lesen-Modus ändern"
|
||||
backup_download: "Backup herunterladen"
|
||||
screened_emails:
|
||||
title: "Gefilterte E-Mails"
|
||||
description: "Wenn jemand ein Konto erstellt, werden die folgenden E-Mail-Adressen überprüft und es wird die Anmeldung blockiert oder eine andere Aktion ausgeführt."
|
||||
|
||||
@ -655,6 +655,8 @@ en:
|
||||
error: "(error)"
|
||||
action: "Send Password Reset Email"
|
||||
set_password: "Set Password"
|
||||
choose_new: "Choose a new password"
|
||||
choose: "Choose a password"
|
||||
|
||||
change_about:
|
||||
title: "Change About Me"
|
||||
@ -1041,6 +1043,7 @@ en:
|
||||
to_continue: "Please Log In"
|
||||
preferences: "You need to be logged in to change your user preferences."
|
||||
forgot: "I don't recall my account details"
|
||||
not_approved: "Your account hasn't been approved yet. You will be notified by email when you are ready to log in."
|
||||
google:
|
||||
title: "with Google"
|
||||
message: "Authenticating with Google (make sure pop up blockers are not enabled)"
|
||||
@ -1063,6 +1066,9 @@ en:
|
||||
title: "with GitHub"
|
||||
message: "Authenticating with GitHub (make sure pop up blockers are not enabled)"
|
||||
|
||||
password_reset:
|
||||
continue: "Continue to %{site_name}"
|
||||
|
||||
emoji_set:
|
||||
apple_international: "Apple/International"
|
||||
google: "Google"
|
||||
@ -1554,12 +1560,8 @@ en:
|
||||
remove_banner: "Remove Banner Topic"
|
||||
|
||||
reply:
|
||||
post:
|
||||
title: 'Reply'
|
||||
# help i.e. tooltop is at controls.reply
|
||||
topic:
|
||||
title: 'Reply'
|
||||
help: 'begin composing a reply to this topic'
|
||||
title: 'Reply'
|
||||
help: 'begin composing a reply to this topic'
|
||||
|
||||
clear_pin:
|
||||
title: "Clear pin"
|
||||
@ -1707,6 +1709,7 @@ en:
|
||||
wiki_last_edited_on: "wiki last edited on"
|
||||
last_edited_on: "post last edited on"
|
||||
reply_as_new_topic: "Reply as linked Topic"
|
||||
reply_as_new_private_message: "Reply as new message to the same recipients"
|
||||
continue_discussion: "Continuing the discussion from {{postLink}}:"
|
||||
follow_quote: "go to the quoted post"
|
||||
show_full: "Show Full Post"
|
||||
@ -1892,7 +1895,8 @@ en:
|
||||
hide: "Hide revision"
|
||||
show: "Show revision"
|
||||
revert: "Revert to this revision"
|
||||
edit_wiki: "Edit wiki"
|
||||
edit_wiki: "Edit Wiki"
|
||||
edit_post: "Edit Post"
|
||||
comparing_previous_to_current_out_of_total: "<strong>{{previous}}</strong> <i class='fa fa-arrows-h'></i> <strong>{{current}}</strong> / {{total}}"
|
||||
displays:
|
||||
inline:
|
||||
|
||||
@ -214,7 +214,7 @@ es:
|
||||
like_count: "Me gusta"
|
||||
topic_count: "Temas"
|
||||
post_count: "Posts"
|
||||
user_count: "Usuarios nuevos"
|
||||
user_count: "Usuarios"
|
||||
active_user_count: "Usuarios activos"
|
||||
contact: "Contáctanos"
|
||||
contact_info: "En caso de un error crítico o un asunto urgente referente a este sitio, por favor, contáctanos en %{contact_info}."
|
||||
@ -1404,10 +1404,10 @@ es:
|
||||
remove_banner: "Remover tema de encabezado"
|
||||
reply:
|
||||
post:
|
||||
title: 'Responder'
|
||||
title: 'Respuesta'
|
||||
topic:
|
||||
title: 'Responder'
|
||||
help: 'comienza a escribir una respuesta a este tema'
|
||||
title: 'Respuesta'
|
||||
help: 'empieza a escribir una respuesta a este tema'
|
||||
clear_pin:
|
||||
title: "Eliminar Destacado"
|
||||
help: "Elimina el estado 'Destacado' de este tema para que no aparezca más en lo más alto de tu lista de temas"
|
||||
@ -1580,7 +1580,7 @@ es:
|
||||
via_auto_generated_email: "este post llegó a través de un email generado automáticamente"
|
||||
whisper: "esto post es un susurro privado para moderadores"
|
||||
wiki:
|
||||
about: "este post es tipo wiki"
|
||||
about: "este es un tema de tipo wiki"
|
||||
archetypes:
|
||||
save: 'Guardar opciones'
|
||||
few_likes_left: "¡Gracias por compartir tu afecto! Te quedan solo unos pocos me gusta para hoy."
|
||||
@ -1707,17 +1707,18 @@ es:
|
||||
hide: "Ocultar revisión."
|
||||
show: "Mostrar revisión."
|
||||
revert: "Volver a esta revisión"
|
||||
edit_wiki: "Editar wiki"
|
||||
comparing_previous_to_current_out_of_total: "<strong>{{previous}}</strong> <i class='fa fa-arrows-h'></i> <strong>{{current}}</strong> / {{total}}"
|
||||
displays:
|
||||
inline:
|
||||
title: "Muestra la producción asistida con adiciones y eleminaciones en línea"
|
||||
button: '<i class="fa fa-square-o"></i> HTML'
|
||||
button: 'HTML'
|
||||
side_by_side:
|
||||
title: "Mostrar la producción asistida estas de lado a lado"
|
||||
button: '<i class="fa fa-columns"></i> HTML'
|
||||
button: 'HTML'
|
||||
side_by_side_markdown:
|
||||
title: "Mostrar las diferencias crudas a la par"
|
||||
button: '<i class="fa fa-columns"></i> Crudo'
|
||||
button: 'Fuente'
|
||||
category:
|
||||
can: 'puede… '
|
||||
none: '(sin categoría)'
|
||||
|
||||
@ -1401,11 +1401,8 @@ et:
|
||||
make_banner: "Tee teema bänneriks"
|
||||
remove_banner: "Eemalda teema bännerist"
|
||||
reply:
|
||||
post:
|
||||
title: 'vasta'
|
||||
topic:
|
||||
title: 'vasta'
|
||||
help: 'alusta selle teema vastuse koostamist'
|
||||
title: 'vasta'
|
||||
help: 'alusta selle teema vastuse koostamist'
|
||||
clear_pin:
|
||||
title: "Kustuta esiletõstmine"
|
||||
help: "Eemalda sellelt teemalt esiletõstetu staatus nii, et ta enam ei ilmuks teemade loetelu tipus"
|
||||
|
||||
@ -214,7 +214,7 @@ fi:
|
||||
like_count: "Tykkäyksiä"
|
||||
topic_count: "Ketjuja"
|
||||
post_count: "Viestejä"
|
||||
user_count: "Uusia käyttäjiä"
|
||||
user_count: "Käyttäjät"
|
||||
active_user_count: "Aktiivisia käyttäjiä"
|
||||
contact: "Yhteystiedot"
|
||||
contact_info: "Sivustoon liittyvissä kiireellisissä asioissa, ota yhteyttä osoitteeseen %{contact_info}."
|
||||
@ -1408,7 +1408,7 @@ fi:
|
||||
title: 'Vastaa'
|
||||
topic:
|
||||
title: 'Vastaa'
|
||||
help: 'aloita kirjottamaan uutta vastausta tähän ketjuun'
|
||||
help: 'aloita kirjoittamaan vastausta tähän ketjuun'
|
||||
clear_pin:
|
||||
title: "Poista kiinnitys"
|
||||
help: "Poista kiinnitys, jotta ketju ei enää pysy listauksen ylimpänä"
|
||||
@ -1581,7 +1581,7 @@ fi:
|
||||
via_auto_generated_email: "tämä viesti saapui automaattisesti generoituna sähköpostina"
|
||||
whisper: "tämä viesti on yksityinen kuiskaus valvojille"
|
||||
wiki:
|
||||
about: "tämä viesti on wiki"
|
||||
about: "tämä viesti on wiki-viesti"
|
||||
archetypes:
|
||||
save: 'Tallennusasetukset'
|
||||
few_likes_left: "Kiitos hyvän mielen levittämisestä! Sinulla on enää muutama tykkäys jäljellä tälle päivälle."
|
||||
@ -1708,17 +1708,18 @@ fi:
|
||||
hide: "Piilota revisio"
|
||||
show: "Näytä revisio"
|
||||
revert: "Palaa tähän revisioon"
|
||||
edit_wiki: "Muokkaa wikiä"
|
||||
comparing_previous_to_current_out_of_total: "<strong>{{previous}}</strong> <i class='fa fa-arrows-h'></i> <strong>{{current}}</strong> / {{total}}"
|
||||
displays:
|
||||
inline:
|
||||
title: "Näytä lisäykset ja poistot tekstin osana"
|
||||
button: '<i class="fa fa-square-o"></i> HTML'
|
||||
button: 'HTML'
|
||||
side_by_side:
|
||||
title: "Näytä muokkauksen versiot vierekkäin"
|
||||
button: '<i class="fa fa-columns"></i> HTML'
|
||||
button: 'HTML'
|
||||
side_by_side_markdown:
|
||||
title: "Näytä viestien lähdekoodit vierekkäin"
|
||||
button: '<i class="fa fa-columns"></i> Teksti'
|
||||
button: 'Raaka'
|
||||
category:
|
||||
can: 'voivat… '
|
||||
none: '(ei aluetta)'
|
||||
@ -1761,7 +1762,7 @@ fi:
|
||||
change_in_category_topic: "Muokkaa kuvausta"
|
||||
already_used: 'Tämä väri on jo käytössä toisella alueella'
|
||||
security: "Turvallisuus"
|
||||
special_warning: "Varoitus: Tämä alue on esituotettu ja sen turvallisuusasetuksia ei voi muuttaa. Jos et halua käyttää sitä, poista se sen sijaan."
|
||||
special_warning: "Varoitus: Tämä on valmiiksi luotu alue, ja sen turvallisuusasetuksia ei voi muuttaa. Jos et näe käyttöä alueelle, älä muuta sen tarkoitusta vaan poista se."
|
||||
images: "Kuvat"
|
||||
auto_close_label: "Sulje ketjut automaattisesti tämän ajan jälkeen:"
|
||||
auto_close_units: "tuntia"
|
||||
@ -2623,12 +2624,17 @@ fi:
|
||||
revoke_admin: "peru ylläpitäjän oikeudet"
|
||||
grant_moderation: "myönnä valvojan oikeudet"
|
||||
revoke_moderation: "peru valvojan oikeudet"
|
||||
backup_operation: "varmuuskopiointi"
|
||||
backup_create: "luo varmuuskopio"
|
||||
deleted_tag: "poistettu tunniste"
|
||||
renamed_tag: "uudelleen nimetty tunniste"
|
||||
revoke_email: "peru sähköpostiosoite"
|
||||
lock_trust_level: "lukitse luottamustaso"
|
||||
unlock_trust_level: "poista luottamustason lukitus"
|
||||
activate_user: "aktivoi käyttäjä"
|
||||
deactivate_user: "poista käyttäjätili käytöstä"
|
||||
change_readonly_mode: "muuta vain luku -tilaa"
|
||||
backup_download: "lataa varmuuskopio"
|
||||
backup_destroy: "tuhoa varmuuskopio"
|
||||
screened_emails:
|
||||
title: "Seulottavat sähköpostiosoitteet"
|
||||
description: "Uuden käyttäjätunnuksen luonnin yhteydessä annettua sähköpostiosoitetta verrataan alla olevaan listaan ja tarvittaessa tunnuksen luonti joko estetään tai suoritetaan muita toimenpiteitä."
|
||||
|
||||
@ -214,7 +214,7 @@ fr:
|
||||
like_count: "J'aime"
|
||||
topic_count: "Sujets"
|
||||
post_count: "Nombre de messages"
|
||||
user_count: "Nouveaux utilisateurs"
|
||||
user_count: "Utilisateurs"
|
||||
active_user_count: "Utilisateurs actifs"
|
||||
contact: "Nous contacter"
|
||||
contact_info: "En cas de problème critique ou urgent sur ce site, veuillez nous contacter : %{contact_info}"
|
||||
@ -1707,17 +1707,18 @@ fr:
|
||||
hide: "Masquer la révision"
|
||||
show: "Afficher la révision"
|
||||
revert: "Revenir à cette révision"
|
||||
edit_wiki: "Modifier le wiki"
|
||||
comparing_previous_to_current_out_of_total: "<strong>{{previous}}</strong> <i class='fa fa-arrows-h'></i> <strong>{{current}}</strong> / {{total}}"
|
||||
displays:
|
||||
inline:
|
||||
title: "Afficher le rendu avec les ajouts et les retraits en ligne"
|
||||
button: '<i class="fa fa-square-o"></i> HTML'
|
||||
button: 'HTML'
|
||||
side_by_side:
|
||||
title: "Afficher les différences de rendu côte-à-côte"
|
||||
button: '<i class="fa fa-columns"></i> HTML'
|
||||
button: 'HTML'
|
||||
side_by_side_markdown:
|
||||
title: "Afficher les différences de la source côte-à-côte"
|
||||
button: '<i class="fa fa-columns"></i> Brut'
|
||||
button: 'Brut'
|
||||
category:
|
||||
can: 'peut… '
|
||||
none: '(aucune catégorie)'
|
||||
|
||||
@ -1145,11 +1145,8 @@ gl:
|
||||
make_banner: "Tema do báner"
|
||||
remove_banner: "Eliminar o tema do báner"
|
||||
reply:
|
||||
post:
|
||||
title: 'Responder'
|
||||
topic:
|
||||
title: 'Responder'
|
||||
help: 'responder a este tema'
|
||||
title: 'Responder'
|
||||
help: 'responder a este tema'
|
||||
clear_pin:
|
||||
title: "Borrar o estado Pegar"
|
||||
help: "Borra o estado Pegado deste tema para que non apareza na banda superior da lista de temas."
|
||||
|
||||
@ -214,7 +214,7 @@ he:
|
||||
like_count: "לייקים"
|
||||
topic_count: "נושאים"
|
||||
post_count: "פוסטים"
|
||||
user_count: "חדשים"
|
||||
user_count: "משתמשים"
|
||||
active_user_count: "משתמשים פעילים"
|
||||
contact: "צרו קשר"
|
||||
contact_info: "במקרה של ארוע קריטי או דחוף המשפיע על האתר, אנא צרו איתנו קשר ב: %{contact_info}."
|
||||
@ -1409,7 +1409,7 @@ he:
|
||||
title: 'תגובה'
|
||||
topic:
|
||||
title: 'תגובה'
|
||||
help: 'התחילו לכתוב תגובה לנושא זה'
|
||||
help: 'התחילו לחבר תגובה לנושא זה'
|
||||
clear_pin:
|
||||
title: "נקה נעיצה"
|
||||
help: "נקה סטטוס נעוץ של נושא זה כדי שהוא לא יופיע עוד בראש רשימת הנושאים שלכם"
|
||||
@ -1582,7 +1582,7 @@ he:
|
||||
via_auto_generated_email: "פוסט זה הגיע דרך מייל שנוצר אוטומטית"
|
||||
whisper: "פוסט זה הוא לחישה פרטית למנחים"
|
||||
wiki:
|
||||
about: "פוסט זה הוא ויקי"
|
||||
about: "הפוסט הוא ויקי"
|
||||
archetypes:
|
||||
save: 'שמור אפשרויות'
|
||||
few_likes_left: "תודה שאתם מפזרים אהבה! נותרו לכם מעט לייקים להיום."
|
||||
@ -1709,17 +1709,18 @@ he:
|
||||
hide: "הסתרת שינויים"
|
||||
show: "הצגת שינויים"
|
||||
revert: "חזרה לגרסה זו"
|
||||
edit_wiki: "עריכת ויקי"
|
||||
comparing_previous_to_current_out_of_total: "<strong>{{previous}}</strong> <i class='fa fa-arrows-h'></i> <strong>{{current}}</strong> / {{total}}"
|
||||
displays:
|
||||
inline:
|
||||
title: "הצג את הפלט עם תוספות והסרות בתוכו"
|
||||
button: '<i class="fa fa-square-o"></i> HTML'
|
||||
button: 'HTML'
|
||||
side_by_side:
|
||||
title: "הצג את הפרשי הפלט אחד ליד השני"
|
||||
button: '<i class="fa fa-columns"></i> HTML'
|
||||
button: 'HTML'
|
||||
side_by_side_markdown:
|
||||
title: "הציגו את ההבדלי המקור הגולמיים זה לצד זה"
|
||||
button: '<i class="fa fa-columns"></i> גלם'
|
||||
button: 'גולמי'
|
||||
category:
|
||||
can: 'יכול… '
|
||||
none: '(ללא קטגוריה)'
|
||||
|
||||
@ -214,7 +214,7 @@ it:
|
||||
like_count: "Mi piace"
|
||||
topic_count: "Argomenti"
|
||||
post_count: "Messaggi"
|
||||
user_count: "Nuovi Utenti"
|
||||
user_count: "Utenti"
|
||||
active_user_count: "Utenti Attivi"
|
||||
contact: "Contattaci"
|
||||
contact_info: "Nel caso di un problema grave o urgente riguardante il sito, per favore contattaci all'indirizzo %{contact_info}."
|
||||
@ -409,11 +409,15 @@ it:
|
||||
muted:
|
||||
title: "Silenziato"
|
||||
description: "Non verrai mai avvertito per i nuovi argomenti in questo gruppo."
|
||||
flair_url: "Immagine Avatar Flair"
|
||||
flair_url_placeholder: "(Facoltativo) URL Immagine o classe Font Awesome"
|
||||
flair_bg_color: "Colore di background Avatar Flair"
|
||||
flair_bg_color_placeholder: "(Facoltativo) Codice esadecimale del colore"
|
||||
flair_color: "Colore Avatar Flair"
|
||||
flair_color_placeholder: "(Facoltativo) Codice esadecimale del colore"
|
||||
flair_preview_icon: "Anteprima Icona"
|
||||
flair_preview_image: "Anteprima Immagine"
|
||||
flair_note: "Nota: Flair sarà mostrato solo per i primary group dell'utente."
|
||||
user_action_groups:
|
||||
'1': "Mi piace - Assegnati"
|
||||
'2': "Mi piace - Ricevuti"
|
||||
@ -619,7 +623,7 @@ it:
|
||||
instructions: "Le immagini di sfondo saranno centrate e per difetto avranno un'ampiezza di 590px."
|
||||
email:
|
||||
title: "Email"
|
||||
instructions: "Mai mostrato pubblicamente"
|
||||
instructions: "mai mostrare al pubblico"
|
||||
ok: "Ti invieremo una email di conferma"
|
||||
invalid: "Inserisci un indirizzo email valido"
|
||||
authenticated: "{{provider}} ha autenticato la tua email"
|
||||
@ -629,13 +633,13 @@ it:
|
||||
other: "Ti invieremo una email solo se non ti si vede da almeno {{count}} minuti."
|
||||
name:
|
||||
title: "Nome"
|
||||
instructions: "Nome completo (facoltativo)"
|
||||
instructions: "il tuo nome completo (opzionale)"
|
||||
instructions_required: "Il tuo nome completo"
|
||||
too_short: "Il nome è troppo breve"
|
||||
ok: "Il nome sembra adeguato"
|
||||
username:
|
||||
title: "Nome utente"
|
||||
instructions: "Deve essere univoco, senza spazi e breve"
|
||||
instructions: "deve essere unico, senza spazi e breve"
|
||||
short_instructions: "Gli utenti possono citarti scrivendo @{{username}}"
|
||||
available: "Il nome utente è disponibile"
|
||||
global_match: "L'email corrisponde al nome utente registrato"
|
||||
@ -745,6 +749,7 @@ it:
|
||||
none: "Non hai ancora invitato nessuno. Puoi invitare persone singole, o più persone insieme <a href='https://meta.discourse.org/t/send-bulk-invites/16468'>caricando un file CSV</a>."
|
||||
text: "Invito di Massa da File"
|
||||
success: "Il file è stato caricato con successo, riceverai un messaggio di notifica quando il processo sarà completato."
|
||||
error: "Spiacenti, il file dovrebbe essere in formato CSV."
|
||||
password:
|
||||
title: "Password"
|
||||
too_short: "La password è troppo breve."
|
||||
@ -752,7 +757,7 @@ it:
|
||||
same_as_username: "La tua password è uguale al tuo nome utente."
|
||||
same_as_email: "La password coincide con l'email."
|
||||
ok: "La password è adeguata"
|
||||
instructions: "Minimo %{count} caratteri."
|
||||
instructions: "Minimo %{count} caratteri"
|
||||
summary:
|
||||
title: "Riepilogo"
|
||||
stats: "Statistiche"
|
||||
@ -1397,11 +1402,8 @@ it:
|
||||
make_banner: "Argomento Annuncio"
|
||||
remove_banner: "Rimuovi Argomento Annuncio"
|
||||
reply:
|
||||
post:
|
||||
title: 'Rispondi'
|
||||
topic:
|
||||
title: 'Rispondi'
|
||||
help: 'inizia a scrivere una risposta a questo argomento'
|
||||
title: 'Rispondi'
|
||||
help: 'inizia a scrivere una risposta a questo argomento'
|
||||
clear_pin:
|
||||
title: "Spunta"
|
||||
help: "Rimuovi la spunta da questo argomento, così non comparirà più in cima alla lista degli argomenti"
|
||||
@ -2331,6 +2333,7 @@ it:
|
||||
individual_event: "Seleziona eventi singoli."
|
||||
verify_certificate: "Verifica il certificato TLS della URL payload"
|
||||
active: "Attivo"
|
||||
groups_filter: "Gruppi triggered"
|
||||
delete_confirm: "Eliminare questo webhook?"
|
||||
topic_event:
|
||||
name: "Evento Argomento"
|
||||
@ -2843,6 +2846,7 @@ it:
|
||||
deactivate_explanation: "Un utente disattivato deve riconvalidare la propria email."
|
||||
suspended_explanation: "Un utente sospeso non può connettersi."
|
||||
block_explanation: "Un utente bloccato non può pubblicare messaggi o iniziare argomenti."
|
||||
staged_explanation: "Un utente staged può solo postare via email in specifici topic."
|
||||
bounce_score_explanation:
|
||||
none: "L'indirizzo email non ha causato nessun errore di ritorno recentemente."
|
||||
some: "Sono stati ricevuti alcuni errori di ritorno per quell'indirizzo email."
|
||||
|
||||
@ -1110,11 +1110,8 @@ ja:
|
||||
make_banner: "バナートピック"
|
||||
remove_banner: "バナートピックを削除"
|
||||
reply:
|
||||
post:
|
||||
title: '返信'
|
||||
topic:
|
||||
title: '返信'
|
||||
help: 'このトピックに返信する'
|
||||
title: '返信'
|
||||
help: 'このトピックに返信する'
|
||||
clear_pin:
|
||||
title: "ピンを解除する"
|
||||
help: "このトピックのピンを外し、トピックリストの先頭に表示されないようにする"
|
||||
|
||||
@ -1151,11 +1151,8 @@ ko:
|
||||
make_banner: "배너 주제"
|
||||
remove_banner: "배너 주제 제거"
|
||||
reply:
|
||||
post:
|
||||
title: '답글'
|
||||
topic:
|
||||
title: '답글'
|
||||
help: '이 주제에 대한 답글 작성 시작'
|
||||
title: '답글'
|
||||
help: '이 주제에 대한 답글 작성 시작'
|
||||
clear_pin:
|
||||
title: "고정 취소"
|
||||
help: "더 이상 목록의 맨 위에 표시하지 않도록 이 주제의 고정 상태를 해제합니다."
|
||||
|
||||
@ -214,7 +214,7 @@ nb_NO:
|
||||
like_count: "Likes"
|
||||
topic_count: "Emner"
|
||||
post_count: "Innlegg"
|
||||
user_count: "Nye brukere"
|
||||
user_count: "Brukere"
|
||||
active_user_count: "Aktive brukere"
|
||||
contact: "Kontakt oss"
|
||||
contact_info: "I tilfelle en kritisk hendelse skulle inntreffe eller det er en hastesak som påvirker siden, ta kontakt på %{contact_info}."
|
||||
@ -244,11 +244,11 @@ nb_NO:
|
||||
preview: "forhåndsvisning"
|
||||
cancel: "avbryt"
|
||||
save: "Lagre endringer"
|
||||
saving: "Lagrer..."
|
||||
saving: "Lagrer…"
|
||||
saved: "Lagret!"
|
||||
upload: "Last opp"
|
||||
uploading: "Laster opp..."
|
||||
uploading_filename: "Laster opp {{filename}}..."
|
||||
uploading: "Laster opp…"
|
||||
uploading_filename: "Laster opp {{filename}}…"
|
||||
uploaded: "Lastet opp!"
|
||||
enable: "Aktiver"
|
||||
disable: "Deaktiver"
|
||||
@ -623,7 +623,7 @@ nb_NO:
|
||||
instructions: "Bakgrunnsbilder vil bli sentrert og ha en forvalgt bredde på 590 piksler."
|
||||
email:
|
||||
title: "E-post"
|
||||
instructions: "Blir aldri vist offentlig"
|
||||
instructions: "aldri vist til offentligheten"
|
||||
ok: "Vi sender deg en e-post for å bekrefte"
|
||||
invalid: "Oppgi en gyldig e-postadresse"
|
||||
authenticated: "Din e-post har blitt autentisert av {{provider}}"
|
||||
@ -633,13 +633,13 @@ nb_NO:
|
||||
other: "Vi sender deg bare e-post hvis vi ikke har sett deg de siste {{count}} minuttene."
|
||||
name:
|
||||
title: "Navn"
|
||||
instructions: "Ditt fulle navn (valgfritt)"
|
||||
instructions: "ditt fulle navn (valgfritt)"
|
||||
instructions_required: "Ditt fulle navn"
|
||||
too_short: "Navnet ditt er for kort."
|
||||
ok: "Navnet ditt ser bra ut."
|
||||
username:
|
||||
title: "Brukernavn"
|
||||
instructions: "Unikt, kort og uten mellomrom."
|
||||
instructions: "unikt, ingen mellomrom, kort"
|
||||
short_instructions: "Folk kan nevne deg som @{{username}}."
|
||||
available: "Ditt brukernavn er tilgjengelig."
|
||||
global_match: "E-post stemmer med det registrerte brukernavnet"
|
||||
@ -647,7 +647,7 @@ nb_NO:
|
||||
not_available: "Ikke tilgjengelig. Prøv {{suggestion}}?"
|
||||
too_short: "Ditt brukernavn er for kort."
|
||||
too_long: "Ditt brukernavn er for langt."
|
||||
checking: "Sjekker brukernavnets tilgjengelighet..."
|
||||
checking: "Sjekker brukernavnets tilgjengelighet…"
|
||||
enter_email: 'Brukernavn funnet; oppgi samsvarende e-post'
|
||||
prefilled: "E-post stemmer med dette registrerte brukernavnet"
|
||||
locale:
|
||||
@ -714,7 +714,7 @@ nb_NO:
|
||||
after_10_minutes: "etter 10 minutt"
|
||||
notification_level_when_replying: "Når jeg publiserer noe i et emner, sett det emnet til"
|
||||
invited:
|
||||
search: "skriv for å søke etter invitasjoner..."
|
||||
search: "skriv for å søke etter invitasjoner…"
|
||||
title: "invitasjoner"
|
||||
user: "Invitert bruker"
|
||||
sent: "Sendt"
|
||||
@ -757,7 +757,7 @@ nb_NO:
|
||||
same_as_username: "Ditt passord er det samme som ditt brukernavn."
|
||||
same_as_email: "Ditt passord er det samme som din e-post."
|
||||
ok: "Passordet ditt ser bra ut"
|
||||
instructions: "Minst %{count} tegn."
|
||||
instructions: "minst %{count} tegn"
|
||||
summary:
|
||||
title: "Oppsummering"
|
||||
stats: "Statistikk"
|
||||
@ -815,7 +815,7 @@ nb_NO:
|
||||
sent_by: "Sendt av"
|
||||
private_message: "melding"
|
||||
the_topic: "emnet"
|
||||
loading: "Laster..."
|
||||
loading: "Laster…"
|
||||
errors:
|
||||
prev_page: "ved lasting"
|
||||
reasons:
|
||||
@ -852,7 +852,7 @@ nb_NO:
|
||||
rate:
|
||||
one: "1 feil/%{duration}"
|
||||
other: "%{count} feil/%{duration}"
|
||||
learn_more: "lær mer..."
|
||||
learn_more: "lær mer…"
|
||||
all_time: 'totalt'
|
||||
all_time_desc: 'totalt antall emner opprettet'
|
||||
year: 'år'
|
||||
@ -890,7 +890,7 @@ nb_NO:
|
||||
disable: "Vis slettede innlegg"
|
||||
private_message_info:
|
||||
title: "Send"
|
||||
invite: "Invitér andre..."
|
||||
invite: "Inviter andre…"
|
||||
remove_allowed_user: "Er du sikker på at du vil fjerne {{name}} fra denne meldingen?"
|
||||
remove_allowed_group: "Vil du virkelig fjerne {{name}} fra denne meldingen?"
|
||||
email: 'E-post'
|
||||
@ -925,9 +925,9 @@ nb_NO:
|
||||
rate_limit: "Vent litt før du logger inn igjen."
|
||||
blank_username_or_password: "Oppgi din e-postadresse eller brukernavn og ditt passord."
|
||||
reset_password: 'Nullstill passord'
|
||||
logging_in: "Logger på..."
|
||||
logging_in: "Logger på…"
|
||||
or: "Eller"
|
||||
authenticating: "Autentiserer..."
|
||||
authenticating: "Autentiserer…"
|
||||
awaiting_confirmation: "Din konto avventer aktivering. Bruk lenken for glemt passord for å sende en ny e-post for aktivering."
|
||||
awaiting_approval: "Din konto har ikke blitt godkjent av en moderator ennå. Du vil motta en e-post når den er godkjent."
|
||||
requires_invite: "Beklager, tilgang til dette forumet kun ved invitasjon."
|
||||
@ -976,7 +976,7 @@ nb_NO:
|
||||
alt: 'Alt'
|
||||
composer:
|
||||
emoji: "Emoji :)"
|
||||
more_emoji: "mer..."
|
||||
more_emoji: "mer…"
|
||||
options: "Alternativer"
|
||||
whisper: "hvisker"
|
||||
unlist: "skjult"
|
||||
@ -984,10 +984,10 @@ nb_NO:
|
||||
toggle_whisper: "Veksle hvisking"
|
||||
toggle_unlisted: "Skjul eller gjør synlig"
|
||||
posting_not_on_topic: "Du svarer på emnet \"{{title}}\", men for øyeblikket ser du på et annet emne."
|
||||
saving_draft_tip: "lagrer..."
|
||||
saving_draft_tip: "lagrer…"
|
||||
saved_draft_tip: "lagret"
|
||||
saved_local_draft_tip: "lagret lokalt"
|
||||
similar_topics: "Emnet ditt har likheter med..."
|
||||
similar_topics: "Emnet ditt har likheter med…"
|
||||
drafts_offline: "utkast offline"
|
||||
group_mentioned:
|
||||
one: "Ved å nevne {{group}}, er du i ferd med å henvende deg til <a href='{{group_link}}'>{{count}} én person</a> – er du sikker?"
|
||||
@ -1023,7 +1023,7 @@ nb_NO:
|
||||
saving: "Lagrer"
|
||||
saved: "Lagret!"
|
||||
saved_draft: "Innleggsutkast. Velg for å fortsette."
|
||||
uploading: "Laster opp..."
|
||||
uploading: "Laster opp…"
|
||||
show_preview: 'se forhånsvisning »'
|
||||
hide_preview: '« skjul forhåndsvisning'
|
||||
quote_post_title: "Siter hele innlegget"
|
||||
@ -1150,7 +1150,7 @@ nb_NO:
|
||||
title: "søk etter emner, innlegg, brukere eller kategorier"
|
||||
no_results: "Ingen resultater funnet."
|
||||
no_more_results: "Ingen flere resultater funnet."
|
||||
searching: "Søker ..."
|
||||
searching: "Søker…"
|
||||
post_format: "#{{post_number}} av {{username}}"
|
||||
context:
|
||||
user: "Søk i innleggene av @{{username}}"
|
||||
@ -1170,7 +1170,7 @@ nb_NO:
|
||||
with_tags:
|
||||
label: Med stikkord
|
||||
filters:
|
||||
label: Returner bare emner/innlegg som...
|
||||
label: Bare returner emner/innlegg som…
|
||||
likes: Jeg likte
|
||||
posted: jeg skrev innlegg i
|
||||
watching: Jeg følger
|
||||
@ -1331,7 +1331,7 @@ nb_NO:
|
||||
go_bottom: "bunn"
|
||||
go: "gå"
|
||||
jump_bottom: "Hopp til nyeste innlegg"
|
||||
jump_prompt: "hopp til..."
|
||||
jump_prompt: "hopp til…"
|
||||
jump_prompt_of: "av %{count} innlegg"
|
||||
jump_prompt_long: "Hvilken melding vil du gå til?"
|
||||
jump_bottom_with_number: "hopp til innlegg %{post_number}"
|
||||
@ -1385,7 +1385,7 @@ nb_NO:
|
||||
delete: "Slett emne"
|
||||
open: "Åpne emne"
|
||||
close: "Lukk emne"
|
||||
multi_select: "Velg innlegg..."
|
||||
multi_select: "Velg innlegg…"
|
||||
auto_close: "Lukk automatisk"
|
||||
pin: "Fest emnet…"
|
||||
unpin: "Løsne emne…"
|
||||
@ -1403,8 +1403,11 @@ nb_NO:
|
||||
make_banner: "Banneremne"
|
||||
remove_banner: "Fjern banneremne"
|
||||
reply:
|
||||
title: 'Svar'
|
||||
help: 'begynn å skrive et svar til dette emnet'
|
||||
post:
|
||||
title: 'Svar'
|
||||
topic:
|
||||
title: 'Svar'
|
||||
help: 'begynn å skrive et svar til dette emnet'
|
||||
clear_pin:
|
||||
title: "Løsne emne"
|
||||
help: "Løsne feste-statusen til dette emnet slik at det ikke lenger vises på toppen av din emneliste"
|
||||
@ -1444,7 +1447,7 @@ nb_NO:
|
||||
banner_note: "Brukere kan fjerne banneret ved å lukke det. Kun et emne kan være banner på en og samme tid. "
|
||||
no_banner_exists: "Det er ingen banneremner. "
|
||||
banner_exists: "Det <strong class='badge badge-notification unread'>er</strong> for øyeblikket et banneremne. "
|
||||
inviting: "Inviterer..."
|
||||
inviting: "Inviterer…"
|
||||
automatically_add_to_groups: "Denne invitasjonen inkluderer også tilgang til disse gruppene:"
|
||||
invite_private:
|
||||
title: 'Invitér til samtale'
|
||||
@ -1530,6 +1533,7 @@ nb_NO:
|
||||
edit: "Redigerer {{link}} {{replyAvatar}} {{username}}"
|
||||
edit_reason: "Begrunnelse:"
|
||||
post_number: "innlegg {{number}}"
|
||||
wiki_last_edited_on: "wikien sist redigert"
|
||||
last_edited_on: "innlegg sist redigert"
|
||||
reply_as_new_topic: "Svar med lenket emne"
|
||||
continue_discussion: "Fortsetter diskusjonen fra {{postLink}}:"
|
||||
@ -1703,17 +1707,18 @@ nb_NO:
|
||||
hide: "Skjul versjon"
|
||||
show: "Vis versjon"
|
||||
revert: "Gå tilbake til denne versjonen"
|
||||
edit_wiki: "Rediger wiki"
|
||||
comparing_previous_to_current_out_of_total: "<strong>{{previous}}</strong> <i class='fa fa-arrows-h'></i> <strong>{{current}}</strong> / {{total}}"
|
||||
displays:
|
||||
inline:
|
||||
title: "Vis endelig tekst med endringene der de er gjort"
|
||||
button: '<i class="fa fa-square-o"></i> HTML'
|
||||
button: 'HTML'
|
||||
side_by_side:
|
||||
title: "Vis endringer i endelig tekst side ved side"
|
||||
button: '<i class="fa fa-columns"></i> HTML'
|
||||
button: 'HTML'
|
||||
side_by_side_markdown:
|
||||
title: "Vis diff for kilderåtekst side ved side"
|
||||
button: '<i class="fa fa-columns"></i> Raw'
|
||||
button: 'Rå'
|
||||
category:
|
||||
can: 'kan…'
|
||||
none: '(no category)'
|
||||
@ -2160,9 +2165,9 @@ nb_NO:
|
||||
custom_message_template_forum: "Hei, du burde ta del i dette forumet!"
|
||||
custom_message_template_topic: "Hei, jeg tenkte du fattet interesse for dette emnet!"
|
||||
safe_mode:
|
||||
enabled: "Sikkert modus er påskrudd, for å gå ut av sikkert modus, lukk dette nettleservinduet"
|
||||
enabled: "Sikkert modus er påskrudd, for å skru av sikkert modus, lukk dette nettleservinduet"
|
||||
admin_js:
|
||||
type_to_filter: "skriv for å filtrere..."
|
||||
type_to_filter: "skriv for å filtrere…"
|
||||
admin:
|
||||
title: 'Discourse Admin'
|
||||
moderator: 'Moderator'
|
||||
@ -2222,7 +2227,7 @@ nb_NO:
|
||||
active: "Aktive"
|
||||
agree: "Godta"
|
||||
agree_title: "Bekreft at denne rapporteringen er gyldig og korrekt"
|
||||
agree_flag_modal_title: "Godta og..."
|
||||
agree_flag_modal_title: "Godta og…"
|
||||
agree_flag_hide_post: "Godta (skjul innlegg + send PM)"
|
||||
agree_flag_hide_post_title: "Skjul dette innlegget og automatisk send brukeren en melding som oppfordrer vedkommende til å foreta endringer"
|
||||
agree_flag_restore_post: "Gi medhold (gjenopprett innlegg)"
|
||||
@ -2237,7 +2242,7 @@ nb_NO:
|
||||
delete_post_defer_flag_title: "Slett innlegg; hvis det er første innlegg, slett emnet"
|
||||
delete_post_agree_flag: "Slett innlegg og si deg enig med rapportering"
|
||||
delete_post_agree_flag_title: "Slett innlegg; hvis det er første innlegg, slett emnet"
|
||||
delete_flag_modal_title: "Slett og..."
|
||||
delete_flag_modal_title: "Slett og…"
|
||||
delete_spammer: "Slett spammer"
|
||||
delete_spammer_title: "Fjern denne brukeren og alle innlegg og emner av brukeren."
|
||||
disagree_flag_unhide_post: "Si deg uenig med rapportering (vis innlegg)"
|
||||
@ -2246,7 +2251,7 @@ nb_NO:
|
||||
disagree_flag_title: "Benekt rapportering som ugyldig eller uriktig"
|
||||
clear_topic_flags: "Ferdig"
|
||||
clear_topic_flags_title: "Emnet har blitt undersøkt og problemer har blitt løst. Klikk Ferdig for å fjerne rapporteringene."
|
||||
more: "(flere svar...)"
|
||||
more: "(flere svar…)"
|
||||
dispositions:
|
||||
agreed: "enig"
|
||||
disagreed: "uenig"
|
||||
@ -2426,12 +2431,12 @@ nb_NO:
|
||||
upload:
|
||||
label: "Last opp"
|
||||
title: "Last opp en sikkerhetskopi til denne instansen"
|
||||
uploading: "Laster opp..."
|
||||
uploading: "Laster opp…"
|
||||
success: "'{{filename}}' har blitt lastet opp."
|
||||
error: "Det oppsto en feil ved opplastingen av '{{filename}}': {{message}}"
|
||||
operations:
|
||||
is_running: "En prosess pågår..."
|
||||
failed: " {{operation}} feilet. Venligst undersøk loggene."
|
||||
is_running: "En prosess pågår…"
|
||||
failed: " {{operation}} mislyktes. Undersøk loggene."
|
||||
cancel:
|
||||
label: "Avbryt"
|
||||
title: "Avbryt den nåværende handlingen"
|
||||
@ -2458,7 +2463,7 @@ nb_NO:
|
||||
confirm: "Er du sikker på at du vil gjenopprette databasen til den tidligere fungerende tilstanden?"
|
||||
export_csv:
|
||||
success: "Eksportering iverksatt. Du vil bli varslet med en melding når prosessen er fullført."
|
||||
failed: "Eksporteringen feilet. Venligst undersøk loggene."
|
||||
failed: "Eksporteringen mislyktes. Undersøk loggene."
|
||||
button_text: "Eksporter"
|
||||
button_title:
|
||||
user: "Eksporter full medlemsliste i CSV format."
|
||||
@ -2560,7 +2565,7 @@ nb_NO:
|
||||
title: "E-poster"
|
||||
settings: "Instillinger"
|
||||
templates: "Maler"
|
||||
preview_digest: "Forhåndsvis Oppsummering"
|
||||
preview_digest: "Forhåndsvis oppsummering"
|
||||
sending_test: "Sender e-post for testing"
|
||||
error: "<b>ERROR</b> - %{server_error}"
|
||||
test_error: "Det oppsto et problem ved utsendelse av e-post for testing. Sjekk e-postinnstillinger nøye, sjekk at verten ikke blokkerer e-posttilkoblinger, og prøv igjen."
|
||||
@ -2586,9 +2591,9 @@ nb_NO:
|
||||
format: "Format"
|
||||
html: "html"
|
||||
text: "tekst"
|
||||
last_seen_user: "Sist Sett Bruker:"
|
||||
last_seen_user: "Bruker sist sett:"
|
||||
no_result: "Ingen resultater funnet for føljetong."
|
||||
reply_key: "Svar ID"
|
||||
reply_key: "Svar-ID"
|
||||
skipped_reason: "Hopp over grunn"
|
||||
incoming_emails:
|
||||
from_address: "Fra"
|
||||
@ -2615,8 +2620,8 @@ nb_NO:
|
||||
filters:
|
||||
title: "Filtrer"
|
||||
user_placeholder: "brukernavn"
|
||||
address_placeholder: "navn@eksempel.com"
|
||||
type_placeholder: "oppsummering, registrering..."
|
||||
address_placeholder: "navn@eksempel.no"
|
||||
type_placeholder: "oppsummering, registrering…"
|
||||
reply_key_placeholder: "svarnøkkel"
|
||||
skipped_reason_placeholder: "grunn"
|
||||
logs:
|
||||
@ -2679,12 +2684,17 @@ nb_NO:
|
||||
revoke_admin: "tilbakekall admin"
|
||||
grant_moderation: "innvilg moderering"
|
||||
revoke_moderation: "tilbakekall moderering"
|
||||
backup_operation: "sikkerhetskopier operasjon"
|
||||
backup_create: "opprett sikkerhetskopi"
|
||||
deleted_tag: "slettet stikkord"
|
||||
renamed_tag: "stikkord med nytt navn"
|
||||
revoke_email: "tilbakekall e-post"
|
||||
lock_trust_level: "lås tillitsnivå"
|
||||
unlock_trust_level: "lås opp tillitsnivå"
|
||||
activate_user: "aktiver bruker"
|
||||
deactivate_user: "deaktiver bruker"
|
||||
change_readonly_mode: "endre skrivebeskyttelse"
|
||||
backup_download: "last ned sikkerhetskopi"
|
||||
backup_destroy: "ødelegg sikkerhetskopi"
|
||||
screened_emails:
|
||||
title: "Kontrollerte e-poster"
|
||||
description: "Når noen forsøker å lage en ny konto, vil de følgende e-postadressene bli sjekket, og registreringen vil bli blokkert, eller en annen handling vil bli utført."
|
||||
@ -2697,11 +2707,11 @@ nb_NO:
|
||||
url: "URL"
|
||||
domain: "Domene"
|
||||
screened_ips:
|
||||
title: "Kontrollerte IPs"
|
||||
title: "Kontrollerte IP-er"
|
||||
description: 'IP-adresser som blir fulgt. Benytt "Tillat" for å hvitliste IP-adresser.'
|
||||
delete_confirm: "Er du sikker på at du vil fjerne regelen for %{ip_address}?"
|
||||
roll_up_confirm: "Er du sikker på at du vil rulle opp vanligvis undersøkte IP-adresser i delnett?"
|
||||
rolled_up_some_subnets: "Fullførte sammenslåingen av blokkerte IP-addresser til disse subnettene: %{subnets}."
|
||||
rolled_up_some_subnets: "Fullførte sammenslåingen av blokkerte IP-adresser til disse subnettene: %{subnets}."
|
||||
rolled_up_no_subnet: "Det var ingenting å slå sammen."
|
||||
actions:
|
||||
block: "Blokker"
|
||||
@ -2727,7 +2737,7 @@ nb_NO:
|
||||
create: 'Legg til Admin Bruker'
|
||||
last_emailed: "Sist kontaktet"
|
||||
not_found: "Beklager, det brukernavner eksisterer ikke i systemet vårt."
|
||||
id_not_found: "Beklager, denne brukerID eksisterer ikke i vårt system."
|
||||
id_not_found: "Denne brukerID-en eksisterer ikke i vårt system."
|
||||
active: "Aktiv"
|
||||
show_emails: "Vis e-poster"
|
||||
nav:
|
||||
@ -2759,7 +2769,7 @@ nb_NO:
|
||||
moderators: 'Moderatorer'
|
||||
blocked: 'Blokkerte brukere'
|
||||
suspended: 'Bannlyste brukere'
|
||||
suspect: 'Mistenkte Brukere'
|
||||
suspect: 'Mistenkte brukere'
|
||||
reject_successful:
|
||||
one: "Avvist 1 bruker."
|
||||
other: "Avviste %{count} brukere."
|
||||
@ -2788,8 +2798,8 @@ nb_NO:
|
||||
blocked: "Blokkert?"
|
||||
staged: "Arrangert?"
|
||||
show_admin_profile: "Admin"
|
||||
edit_title: "Rediger Tittel"
|
||||
save_title: "Lagre Tittel"
|
||||
edit_title: "Rediger tittel"
|
||||
save_title: "Lagre tittel"
|
||||
refresh_browsers: "Tving nettleser refresh"
|
||||
refresh_browsers_message: "Melding sendt til alle klienter!"
|
||||
show_public_profile: "Vis offentlig profil"
|
||||
@ -2891,8 +2901,8 @@ nb_NO:
|
||||
flagged_by_users: "Brukere som rapporterte"
|
||||
likes_given: "Likes tildelt"
|
||||
likes_received: "Likes mottatt"
|
||||
likes_received_days: "Likes Mottatt: unike dager"
|
||||
likes_received_users: "Likes Mottatt: unike brukere"
|
||||
likes_received_days: "Likes mottatt: Unike dager"
|
||||
likes_received_users: "Likes mottatt: Unike brukere"
|
||||
qualifies: "Kvalifiserer til tillitsnivå 3."
|
||||
does_not_qualify: "Kvalifiserer ikke til tillitsnivå 3."
|
||||
will_be_promoted: "Vil snart forfremmes."
|
||||
@ -2909,7 +2919,7 @@ nb_NO:
|
||||
external_avatar_url: "Profilbilde URL"
|
||||
user_fields:
|
||||
title: "Brukerfelter"
|
||||
help: "Legg til felt som dine brukere kan fylle ut."
|
||||
help: "Legg til felter som dine brukere kan fylle ut."
|
||||
create: "Opprett brukerfelt"
|
||||
untitled: "Uten tittel"
|
||||
name: "Feltnavn"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1367,11 +1367,8 @@ pt:
|
||||
make_banner: "Tópico de Faixa"
|
||||
remove_banner: "Remover Tópico de Faixa"
|
||||
reply:
|
||||
post:
|
||||
title: 'Responder'
|
||||
topic:
|
||||
title: 'Responder'
|
||||
help: 'começa a compor uma resposta a este tópico'
|
||||
title: 'Responder'
|
||||
help: 'começa a compor uma resposta a este tópico'
|
||||
clear_pin:
|
||||
title: "Remover destaque"
|
||||
help: "Remover destaque deste tópico para que o mesmo deixe de aparecer no topo da sua lista de tópicos"
|
||||
|
||||
@ -214,7 +214,7 @@ pt_BR:
|
||||
like_count: "Curtidas"
|
||||
topic_count: "Tópicos"
|
||||
post_count: "Mensagens"
|
||||
user_count: "Novos Usuários"
|
||||
user_count: "Usuários"
|
||||
active_user_count: "Usuários Ativos"
|
||||
contact: "Contate-nos"
|
||||
contact_info: "Em caso de um evento crítico ou de urgência afetando este site, por favor contacte-nos em %{contact_info}."
|
||||
@ -326,6 +326,17 @@ pt_BR:
|
||||
add_user_to_group: "Adicionar usuário"
|
||||
remove_user_from_group: "Remover usuário"
|
||||
groups:
|
||||
logs:
|
||||
title: "Registros"
|
||||
subject: "Assunto"
|
||||
details: "Detalhes"
|
||||
from: "De"
|
||||
to: "Para"
|
||||
edit:
|
||||
title: 'Editar Grupo'
|
||||
full_name: 'Nome Completo'
|
||||
add_members: "Adicionar Membros"
|
||||
delete_member_confirm: "Remover '%{username}' do grupo '%{group}'?"
|
||||
add: "Adicionar"
|
||||
selector_placeholder: "Adicionar membros"
|
||||
owner: "proprietário"
|
||||
@ -1144,6 +1155,7 @@ pt_BR:
|
||||
new_messages_marker: "última visita"
|
||||
bulk:
|
||||
select_all: "Selecionar Tudo"
|
||||
clear_all: "Limpar Tudo"
|
||||
unlist_topics: "Tópicos Não Listados"
|
||||
reset_read: "Redefinir Lido"
|
||||
delete: "Apagar Tópicos"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user