mirror of
https://github.com/discourse/discourse.git
synced 2024-11-25 02:11:08 -06:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
807f763fb0
@ -21,9 +21,16 @@ class TopicsController < ApplicationController
|
||||
|
||||
before_filter :consider_user_for_promotion, only: :show
|
||||
|
||||
skip_before_filter :check_xhr, only: [:avatar, :show, :feed]
|
||||
skip_before_filter :check_xhr, only: [:avatar, :show, :feed, :redirect_to_show]
|
||||
caches_action :avatar, cache_path: Proc.new {|c| "#{c.params[:post_number]}-#{c.params[:topic_id]}" }
|
||||
|
||||
def redirect_to_show
|
||||
topic_query = ((num = params[:id].to_i) > 0 and num.to_s == params[:id].to_s) ? Topic.where(id: num) : Topic.where(slug: params[:id])
|
||||
topic = topic_query.includes(:category).first
|
||||
raise Discourse::NotFound unless topic
|
||||
redirect_to topic.relative_url
|
||||
end
|
||||
|
||||
def show
|
||||
opts = params.slice(:username_filters, :best_of, :page, :post_number, :posts_before, :posts_after, :best)
|
||||
@topic_view = TopicView.new(params[:id] || params[:topic_id], current_user, opts)
|
||||
|
@ -85,6 +85,8 @@ class Category < ActiveRecord::Base
|
||||
if name.present?
|
||||
self.slug = Slug.for(name)
|
||||
|
||||
return if self.slug.blank?
|
||||
|
||||
# If a category with that slug already exists, set the slug to nil so the category can be found
|
||||
# another way.
|
||||
category = Category.where(slug: self.slug)
|
||||
|
@ -25,7 +25,7 @@
|
||||
<p><%= t 'powered_by_html' %></p>
|
||||
|
||||
<% content_for :head do %>
|
||||
<%= auto_discovery_link_tag(@topic_view, {action: :feed, format: :rss}, title: t('rss_posts_in_topic', topic: @topic_view.title), type: 'application/rss+xml') %>
|
||||
<%= auto_discovery_link_tag(@topic_view, {action: :feed, format: :rss, 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') %>
|
||||
<%= crawlable_meta_data(title: @topic_view.title,
|
||||
description: @topic_view.summary,
|
||||
image: @topic_view.image_url) %>
|
||||
|
@ -316,6 +316,9 @@ de:
|
||||
facebook:
|
||||
title: "Mit Facebook"
|
||||
message: "Authentisierung via Facebook (stelle sicher, dass der Popup-Blocker deaktiviert ist)"
|
||||
cas:
|
||||
title: "Mit CAS"
|
||||
message: "Authentisierung via CAS (stelle sicher, dass der Popup-Blocker deaktiviert ist)"
|
||||
yahoo:
|
||||
title: "Mit Yahoo"
|
||||
message: "Authentisierung via Yahoo (stelle sicher, dass der Popup-Blocker deaktiviert ist)"
|
||||
@ -432,6 +435,10 @@ de:
|
||||
no_results: "Nichts gefunden."
|
||||
searching: "Suche ..."
|
||||
|
||||
prefer:
|
||||
user: "Die Suche bevorzugt Resultate von @{{username}}"
|
||||
category: "Die Suche bevorzugt Resultate in der Kategorie {{category}}"
|
||||
|
||||
site_map: "Gehe zu einer anderen Themenübersicht oder Kategorie"
|
||||
go_back: 'Zurück'
|
||||
current_user: 'Gehe zu deinem Nutzerprofil'
|
||||
@ -498,6 +505,11 @@ de:
|
||||
toggle_information: "Themendetails ein-/ausblenden"
|
||||
read_more_in_category: "Möchtest Du mehr lesen? Finde andere Themen in {{catLink}} oder {{latestLink}}."
|
||||
read_more: "Möchtest Du mehr lesen? {{catLink}} oder {{latestLink}}."
|
||||
|
||||
# keys ending with _MF use message format, see /spec/components/js_local_helper_spec.rb for samples
|
||||
read_more_in_category_MF: "Du {UNREAD, plural, one {hast <a href='/unread'>eine ungelesene</a>} other {hast <a href='/unread'># ungelesene</a>}} und {NEW, plural, one {<a href='/new'>ein neues</a> Thema} other {<a href='/new'># neue</a> Themen}} übrig, oder entdecke neue Themen in {catLink}"
|
||||
read_more_MF: "Du {UNREAD, plural, one {hast <a href='/unread'>eine ungelesene</a>} other {hast <a href='/unread'># ungelesene</a>}} und {NEW, plural, one {<a href='/new'>ein neues</a> Thema} other {<a href='/new'># neue</a> Themen}} übrig, oder {latestLink}"
|
||||
|
||||
browse_all_categories: Zeige alle Kategorien
|
||||
|
||||
view_latest_topics: zeige aktuelle Themen
|
||||
@ -851,7 +863,7 @@ de:
|
||||
replies: "Antworten"
|
||||
views_long: "Dieses Thema wurde {{number}} aufgerufen"
|
||||
activity: "Aktivität"
|
||||
likes: "Gefällt mir"
|
||||
likes: "Gefällt mir"
|
||||
top_contributors: "Teilnehmer"
|
||||
category_title: "Kategorie"
|
||||
history: "Verlauf"
|
||||
@ -909,8 +921,8 @@ de:
|
||||
moderator: 'Moderator'
|
||||
|
||||
dashboard:
|
||||
title: "Administratorkonsole"
|
||||
version: "Installierte Version"
|
||||
title: "Übersicht"
|
||||
version: "Version"
|
||||
up_to_date: "Discourse ist aktuell."
|
||||
critical_available: "Ein kritisches Update ist verfügbar."
|
||||
updates_available: "Updates sind verfügbar."
|
||||
|
@ -379,6 +379,7 @@ de:
|
||||
queue_size_warning: 'Die Anzahl der Aktionen in der Warteschlange ist mit %{queue_size} ziemlich hoch. Das könnte auf ein Problem mit dem Sidekiq Prozess(en) hinweisen, oder du musst mehr Sidekiq Arbeiter hinzufügen.'
|
||||
memory_warning: 'Dein Server läuft mit weniger als 1 GB Hauptspeicher. Mindestens 1 GB Hauptspeicher werden empfohlen.'
|
||||
facebook_config_warning: 'Der Server erlaubt die Anmeldung mit Facebook (enable_facebook_logins), aber die App ID und der Geheimcode sind nicht gesetzt. Besuche <a href="/admin/site_settings">die Einstellungen</a> um die fehlenden Einträge hinzuzufügen. <a href="https://github.com/discourse/discourse/wiki/The-Discourse-Admin-Quick-Start-Guide#enable-facebook-logins" target="_blank">Besuche den Leitfaden um mehr zu erfahren</a>.'
|
||||
cas_config_warning: 'Der Server erlaubt die Anmeldung mit CAS (enable_cas_logins), aber der Hostname und die Domäne sind nicht gesetzt.'
|
||||
twitter_config_warning: 'Der Server erlaubt die Anmeldung mit Facebook Twitter (enable_twitter_logins), aber der Schlüssel und der Geheimcode sind nicht gesetzt. Besuche <a href="/admin/site_settings">die Einstellungen</a> um die fehlenden Einträge hinzuzufügen. <a href="https://github.com/discourse/discourse/wiki/The-Discourse-Admin-Quick-Start-Guide#enable-twitter-logins" target="_blank">Besuche den Leitfaden um mehr zu erfahren</a>.'
|
||||
github_config_warning: 'Der Server erlaubt die Anmeldung mit Facebook GitHub (enable_github_logins), aber die Kunden ID und der Geheimcode sind nicht gesetzt. Besuche <a href="/admin/site_settings">die Einstellungen</a> um die fehlenden Einträge hinzuzufügen. <a href="https://github.com/discourse/discourse/wiki/The-Discourse-Admin-Quick-Start-Guide" target="_blank">Besuche den Leitfaden um mehr zu erfahren</a>.'
|
||||
failing_emails_warning: 'Es konnten insgesamt %{num_failed_jobs} Mails nicht versendet werden. Bitte überprüfe die Einstellungen in config/environments/production.rb und stelle die Richtigkeit der config.action_mailer Einstellungen. <a href="/sidekiq/retries" target="_blank">Zu den Fehlern in Sidekiq</a>.'
|
||||
@ -386,6 +387,7 @@ de:
|
||||
contact_email_missing: "Du hast noch keine Kontaktmail für die Seite hinterlegt. Bitte hinterlege diese in den <a href='/admin/site_settings'>Einstellungen</a> (siehe contact_email)."
|
||||
contact_email_invalid: "Die Kontaktmail der Seite ist ungültig. Bitte bearbeite diese in den <a href='/admin/site_settings'>Einstellungen</a> (siehe contact_email)."
|
||||
title_nag: "Der Titel der Seite wurde noch nicht angepasst. Bitte bearbeite diesen in den <a href='/admin/site_settings'>Einstellungen</a>."
|
||||
gmail_for_email_warning: "Deine Seite verwendet Gmail um Mails zu senden. <a href='http://support.google.com/a/bin/answer.py?hl=en&answer=166852' target='_blank'>Gmail hat eine Limite zum Senden von Mails</a>. Um die Mail-Zustellung zu gewährleisten, solltest du einen anderen Mail Service in Erwägung ziehen."
|
||||
|
||||
content_types:
|
||||
education_new_reply:
|
||||
@ -488,13 +490,15 @@ de:
|
||||
email_domains_whitelist: "Eine durch senkrechte Striche getrennte Liste von erlaubte Maildomains. WARNUNG: Benutzer mit Mailadressen anderer Domains können sich nicht registrieren."
|
||||
version_checks: "Erfrage Versionsupdate bei Discourse Hub und zeige Versionsbenachrichtigungen auf der Administratorkonsole /admin."
|
||||
|
||||
port: "Benutze diesen HTTP-Port anstatt den Standardport 80. Diese Feld leer lassen heißt 'keinen'. Dient hauptsächlich Entwicklungszwecken."
|
||||
force_hostname: "Spezifiziere einen Hostnamen in der URL. Dieses Feld leer lassen heißt 'keinen'. Dient hauptsächlich Entwicklungszwecken."
|
||||
port: "NUR FÜR ENTWICKLER! ACHTUNG! Benutze diesen HTTP-Port anstatt den Standardport 80. Diese Feld leer lassen heißt 'keinen'. Dient hauptsächlich Entwicklungszwecken."
|
||||
force_hostname: "NUR FÜR ENTWICKLER! ACHTUNG! Spezifiziere einen Hostnamen in der URL. Dieses Feld leer lassen heißt 'keinen'. Dient hauptsächlich Entwicklungszwecken."
|
||||
|
||||
invite_expiry_days: "Tage, die Nutzereinladungen gültig bleiben."
|
||||
|
||||
# TODO: perhaps we need a way of protcting these settings for hosted solution, global settings ...
|
||||
|
||||
enable_local_logins: "Aktiviere lokale Authentisierung"
|
||||
enable_local_account_create: "Aktiviere lokale Kontoerstellung"
|
||||
enable_google_logins: "Aktiviere Google Authentisierung."
|
||||
enable_yahoo_logins: "Aktiviere Yahoo Authentisierung."
|
||||
|
||||
@ -506,6 +510,10 @@ de:
|
||||
facebook_app_id: "App-ID für Facebook Authentisierung, registriert auf https://developers.facebook.com/apps"
|
||||
facebook_app_secret: "App Secret für Facebook Authentisierung, registriert auf https://developers.facebook.com/apps"
|
||||
|
||||
enable_cas_logins: "Aktiviere CAS Authentisierung"
|
||||
cas_hostname: "Hostname für den CAS Server"
|
||||
cas_domainname: "Domäne für die generierten Mailadresses des CAS Server"
|
||||
|
||||
enable_github_logins: "Aktiviere Github Authentisierung (benötigt github_client_id und github_client_secret)."
|
||||
github_client_id: "Client-ID für Github Authentisierung, registriert auf https://github.com/settings/applications"
|
||||
github_client_secret: "Client Secret für Github Authentisierung, registriert auf https://github.com/settings/applications"
|
||||
|
@ -182,7 +182,7 @@ Discourse::Application.routes.draw do
|
||||
get 'search' => 'search#query'
|
||||
|
||||
# Topics resource
|
||||
get 't/:id' => 'topics#show'
|
||||
get 't/:id' => 'topics#redirect_to_show'
|
||||
delete 't/:id' => 'topics#destroy'
|
||||
put 't/:id' => 'topics#update'
|
||||
post 't' => 'topics#create'
|
||||
|
@ -6,7 +6,8 @@
|
||||
module Slug
|
||||
|
||||
def self.for(string)
|
||||
string.parameterize.gsub("_", "-")
|
||||
slug = string.parameterize.gsub("_", "-")
|
||||
slug =~ /[^\d]/ ? slug : '' # Reject slugs that only contain numbers, because they would be indistinguishable from id's.
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -43,5 +43,13 @@ describe Slug do
|
||||
Slug.for("o_o_o").should == "o-o-o"
|
||||
end
|
||||
|
||||
it "doesn't generate slugs that are just numbers" do
|
||||
Slug.for('123').should be_blank
|
||||
end
|
||||
|
||||
it "doesn't generate slugs that are just numbers" do
|
||||
Slug.for('電車男 2').should be_blank
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
@ -369,18 +369,18 @@ describe TopicsController do
|
||||
let!(:p2) { Fabricate(:post, user: topic.user) }
|
||||
|
||||
it 'shows a topic correctly' do
|
||||
xhr :get, :show, id: topic.id
|
||||
xhr :get, :show, topic_id: topic.id, slug: topic.slug
|
||||
response.should be_success
|
||||
end
|
||||
|
||||
it 'records a view' do
|
||||
lambda { xhr :get, :show, id: topic.id }.should change(View, :count).by(1)
|
||||
lambda { xhr :get, :show, topic_id: topic.id, slug: topic.slug }.should change(View, :count).by(1)
|
||||
end
|
||||
|
||||
it 'tracks a visit for all html requests' do
|
||||
current_user = log_in(:coding_horror)
|
||||
TopicUser.expects(:track_visit!).with(topic, current_user)
|
||||
get :show, id: topic.id
|
||||
get :show, topic_id: topic.id, slug: topic.slug
|
||||
end
|
||||
|
||||
context 'consider for a promotion' do
|
||||
@ -394,7 +394,7 @@ describe TopicsController do
|
||||
it "reviews the user for a promotion if they're new" do
|
||||
user.update_column(:trust_level, TrustLevel.levels[:newuser])
|
||||
Promotion.any_instance.expects(:review)
|
||||
get :show, id: topic.id
|
||||
get :show, topic_id: topic.id, slug: topic.slug
|
||||
end
|
||||
end
|
||||
|
||||
@ -403,40 +403,59 @@ describe TopicsController do
|
||||
it 'grabs first page when no filter is provided' do
|
||||
SiteSetting.stubs(:posts_per_page).returns(20)
|
||||
TopicView.any_instance.expects(:filter_posts_in_range).with(0, 20)
|
||||
xhr :get, :show, id: topic.id
|
||||
xhr :get, :show, topic_id: topic.id, slug: topic.slug
|
||||
end
|
||||
|
||||
it 'grabs first page when first page is provided' do
|
||||
SiteSetting.stubs(:posts_per_page).returns(20)
|
||||
TopicView.any_instance.expects(:filter_posts_in_range).with(0, 20)
|
||||
xhr :get, :show, id: topic.id, page: 1
|
||||
xhr :get, :show, topic_id: topic.id, slug: topic.slug, page: 1
|
||||
end
|
||||
|
||||
it 'grabs correct range when a page number is provided' do
|
||||
SiteSetting.stubs(:posts_per_page).returns(20)
|
||||
TopicView.any_instance.expects(:filter_posts_in_range).with(20, 40)
|
||||
xhr :get, :show, id: topic.id, page: 2
|
||||
xhr :get, :show, topic_id: topic.id, slug: topic.slug, page: 2
|
||||
end
|
||||
|
||||
it 'delegates a post_number param to TopicView#filter_posts_near' do
|
||||
TopicView.any_instance.expects(:filter_posts_near).with(p2.post_number)
|
||||
xhr :get, :show, id: topic.id, post_number: p2.post_number
|
||||
xhr :get, :show, topic_id: topic.id, slug: topic.slug, post_number: p2.post_number
|
||||
end
|
||||
|
||||
it 'delegates a posts_after param to TopicView#filter_posts_after' do
|
||||
TopicView.any_instance.expects(:filter_posts_after).with(p1.post_number)
|
||||
xhr :get, :show, id: topic.id, posts_after: p1.post_number
|
||||
xhr :get, :show, topic_id: topic.id, slug: topic.slug, posts_after: p1.post_number
|
||||
end
|
||||
|
||||
it 'delegates a posts_before param to TopicView#filter_posts_before' do
|
||||
TopicView.any_instance.expects(:filter_posts_before).with(p2.post_number)
|
||||
xhr :get, :show, id: topic.id, posts_before: p2.post_number
|
||||
xhr :get, :show, topic_id: topic.id, slug: topic.slug, posts_before: p2.post_number
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe 'redirect_to_show' do
|
||||
let(:topic) { Fabricate(:topic) }
|
||||
|
||||
it 'raises an error if topic is not found' do
|
||||
get :redirect_to_show, id: 121212121212
|
||||
expect(response.status).to eq(404)
|
||||
end
|
||||
|
||||
it 'redirects to the correct topic when given its id' do
|
||||
get :redirect_to_show, id: topic.id
|
||||
expect(response).to redirect_to(topic.relative_url)
|
||||
end
|
||||
|
||||
it 'redirects to the correct topic when given its slug' do
|
||||
get :redirect_to_show, id: topic.slug
|
||||
expect(response).to redirect_to(topic.relative_url)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#feed' do
|
||||
let(:topic) { Fabricate(:post).topic }
|
||||
|
||||
|
@ -104,6 +104,14 @@ describe Category do
|
||||
end
|
||||
end
|
||||
|
||||
describe 'slug would be a number' do
|
||||
let(:category) { Fabricate(:category, name: "電車男 2") }
|
||||
|
||||
it 'creates a blank slug' do
|
||||
category.slug.should be_blank
|
||||
end
|
||||
end
|
||||
|
||||
describe 'after create' do
|
||||
before do
|
||||
@category = Fabricate(:category, name: 'Amazing Category')
|
||||
|
Loading…
Reference in New Issue
Block a user