diff --git a/bingo_web.rb b/bingo_web.rb index ee1369a..96ca286 100644 --- a/bingo_web.rb +++ b/bingo_web.rb @@ -97,7 +97,13 @@ class BingoWeb < Sinatra::Base erb :sitemap, layout: false end - get %r{/(ru|en|uk)/?} do |locale| + # One URL per page: /en/ is a duplicate of /en. + get %r{/(ru|en|uk)/} do |locale| + qs = request.query_string + redirect "/#{locale}#{"?#{qs}" unless qs.empty?}", 301 + end + + get %r{/(ru|en|uk)} do |locale| @locale = locale @view = Bingo::VIEWS.include?(params[:view]) ? params[:view] : 'all' @board = Bingo::Board.load(@view) diff --git a/test/bingo_test.rb b/test/bingo_test.rb index b81e22a..ef13ea2 100644 --- a/test/bingo_test.rb +++ b/test/bingo_test.rb @@ -136,6 +136,7 @@ class BingoTest < Minitest::Test assert last_response.ok? assert_includes last_response.body, 'noindex, follow' assert_includes last_response.body, 'href="/en?view=operational"' # language links keep the view + assert_includes last_response.body, '' # followed internal link assert_includes last_response.body, 'rel="canonical" href="https://example.org/ru"' get '/ru?view=bogus' assert_includes last_response.body, 'index, follow, max-image-preview' @@ -183,6 +184,12 @@ class BingoTest < Minitest::Test assert_equal 404, last_response.status end + def test_trailing_slash_redirects + get '/en/', view: 'operational' + assert_equal 301, last_response.status + assert_equal 'http://example.org/en?view=operational', last_response.location + end + def test_root_varies_on_language get '/' assert_equal 'Accept-Language', last_response.headers['Vary'] diff --git a/views/bingo/index.erb b/views/bingo/index.erb index 66c136a..c9c85d0 100644 --- a/views/bingo/index.erb +++ b/views/bingo/index.erb @@ -5,7 +5,7 @@