Add language settings for users, and translate titles to French
This commit is contained in:
parent
497768610d
commit
8d754ec7aa
@ -2,7 +2,7 @@ class ApplicationController < ActionController::Base
|
|||||||
include Authentication
|
include Authentication
|
||||||
include Pundit::Authorization
|
include Pundit::Authorization
|
||||||
|
|
||||||
before_action :set_title, :set_current_user
|
before_action :set_title, :set_current_user, :set_lang
|
||||||
after_action :verify_authorized
|
after_action :verify_authorized
|
||||||
|
|
||||||
# Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has.
|
# Only allow modern browsers supporting webp images, web push, badges, import maps, CSS nesting, and CSS :has.
|
||||||
@ -23,6 +23,10 @@ class ApplicationController < ActionController::Base
|
|||||||
@current_user = current_user
|
@current_user = current_user
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_lang
|
||||||
|
I18n.locale = @current_user.lang
|
||||||
|
end
|
||||||
|
|
||||||
def user_not_authorized(exception)
|
def user_not_authorized(exception)
|
||||||
policy_name = exception.policy.class.to_s.underscore
|
policy_name = exception.policy.class.to_s.underscore
|
||||||
|
|
||||||
|
@ -55,6 +55,6 @@ class UsersController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def user_params
|
def user_params
|
||||||
params.expect(user: [ :username, :email_address, :password ])
|
params.expect(user: [ :username, :email_address, :lang, :password ])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
3
app/lib/languages.rb
Normal file
3
app/lib/languages.rb
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module Languages
|
||||||
|
AVAILABLE_LANGUAGES = [ { id: "en", name: "English" }, { id: "fr", name: "French" } ]
|
||||||
|
end
|
@ -5,6 +5,7 @@
|
|||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
# admin :boolean default(FALSE), not null
|
# admin :boolean default(FALSE), not null
|
||||||
# email_address :string not null
|
# email_address :string not null
|
||||||
|
# lang :string default("en")
|
||||||
# password_digest :string not null
|
# password_digest :string not null
|
||||||
# username :string
|
# username :string
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
@ -22,4 +23,5 @@ class User < ApplicationRecord
|
|||||||
normalizes :email_address, with: ->(e) { e.strip.downcase }
|
normalizes :email_address, with: ->(e) { e.strip.downcase }
|
||||||
|
|
||||||
validates :username, presence: true, uniqueness: true
|
validates :username, presence: true, uniqueness: true
|
||||||
|
validates :lang, inclusion: { in: Languages::AVAILABLE_LANGUAGES.map { |lang| lang[:id] } }
|
||||||
end
|
end
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
= form_with model: user, method: method do |form|
|
= form_with model: user, method: method do |form|
|
||||||
- if method == :patch
|
- if method == :patch
|
||||||
h4 General settings
|
h4 General settings
|
||||||
|
|
||||||
.row.mb-3
|
.row.mb-3
|
||||||
.col
|
.col
|
||||||
.input-group
|
.input-group
|
||||||
@ -8,11 +9,20 @@
|
|||||||
.form-floating
|
.form-floating
|
||||||
= form.text_field :username, autocomplete: "off", class: "form-control"
|
= form.text_field :username, autocomplete: "off", class: "form-control"
|
||||||
= form.label :username, class: "required"
|
= form.label :username, class: "required"
|
||||||
|
|
||||||
.row.mb-3
|
.row.mb-3
|
||||||
.col
|
.col
|
||||||
.form-floating
|
.form-floating
|
||||||
= form.text_field :email_address, autocomplete: "off", class: "form-control"
|
= form.text_field :email_address, autocomplete: "off", class: "form-control"
|
||||||
= form.label :email_address, class: "required"
|
= form.label :email_address, class: "required"
|
||||||
|
|
||||||
|
.row.mb-3
|
||||||
|
.col
|
||||||
|
.form-floating
|
||||||
|
= form.select :lang, Languages::AVAILABLE_LANGUAGES.map { |lang| [ lang[:name], lang[:id] ] }, {}, class: "form-select"
|
||||||
|
= form.label :lang
|
||||||
|
| Language
|
||||||
|
|
||||||
- if method == :post
|
- if method == :post
|
||||||
.row.mb-3
|
.row.mb-3
|
||||||
.col
|
.col
|
||||||
@ -23,6 +33,7 @@
|
|||||||
|
|
||||||
- if method == :patch
|
- if method == :patch
|
||||||
h4.mt-5 Change password
|
h4.mt-5 Change password
|
||||||
|
|
||||||
= form_with model: user, method: method do |form|
|
= form_with model: user, method: method do |form|
|
||||||
.row.mb-3
|
.row.mb-3
|
||||||
.col
|
.col
|
||||||
|
@ -14,6 +14,7 @@ module PuzzleScoreboard
|
|||||||
# Please, add to the `ignore` list any other `lib` subdirectories that do
|
# Please, add to the `ignore` list any other `lib` subdirectories that do
|
||||||
# not contain `.rb` files, or that should not be reloaded or eager loaded.
|
# not contain `.rb` files, or that should not be reloaded or eager loaded.
|
||||||
# Common ones are `templates`, `generators`, or `middleware`, for example.
|
# Common ones are `templates`, `generators`, or `middleware`, for example.
|
||||||
|
config.autoload_paths << Rails.root.join("lib")
|
||||||
config.autoload_lib(ignore: %w[assets tasks])
|
config.autoload_lib(ignore: %w[assets tasks])
|
||||||
|
|
||||||
# Configuration for the application, engines, and railties goes here.
|
# Configuration for the application, engines, and railties goes here.
|
||||||
@ -23,5 +24,8 @@ module PuzzleScoreboard
|
|||||||
#
|
#
|
||||||
# config.time_zone = "Central Time (US & Canada)"
|
# config.time_zone = "Central Time (US & Canada)"
|
||||||
# config.eager_load_paths << Rails.root.join("extras")
|
# config.eager_load_paths << Rails.root.join("extras")
|
||||||
|
|
||||||
|
config.i18n.default_locale = :en
|
||||||
|
config.i18n.available_locales = [ :en, :fr ]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
37
config/locales/fr.yml
Normal file
37
config/locales/fr.yml
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
fr:
|
||||||
|
completions:
|
||||||
|
edit:
|
||||||
|
title: "Modifier la complétion"
|
||||||
|
new:
|
||||||
|
title: "Nouvelle complétion"
|
||||||
|
contests:
|
||||||
|
edit:
|
||||||
|
title: "Paramètres du concours"
|
||||||
|
index:
|
||||||
|
title: "Bienvenue %{username}!"
|
||||||
|
new:
|
||||||
|
title: "Nouveau concours"
|
||||||
|
scoreboard:
|
||||||
|
title: "%{name}"
|
||||||
|
show:
|
||||||
|
title: "%{name}"
|
||||||
|
contestants:
|
||||||
|
edit:
|
||||||
|
title: "Participant"
|
||||||
|
new:
|
||||||
|
title: "Nouveau.elle participant.e"
|
||||||
|
puzzles:
|
||||||
|
edit:
|
||||||
|
title: "Modifier le puzzle"
|
||||||
|
new:
|
||||||
|
title: "Nouveau puzzle"
|
||||||
|
sessions:
|
||||||
|
new:
|
||||||
|
title: "Se connecter à l'app Public Scoreboard"
|
||||||
|
users:
|
||||||
|
edit:
|
||||||
|
title: "Mes paramètres"
|
||||||
|
index:
|
||||||
|
title: "Tous.tes les utilisateur.ices"
|
||||||
|
new:
|
||||||
|
title: "Nouveau.elle utilisateur.ice"
|
5
db/migrate/20250327111835_add_lang_to_user.rb
Normal file
5
db/migrate/20250327111835_add_lang_to_user.rb
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
class AddLangToUser < ActiveRecord::Migration[8.0]
|
||||||
|
def change
|
||||||
|
add_column :users, :lang, :string, default: 'en'
|
||||||
|
end
|
||||||
|
end
|
3
db/schema.rb
generated
3
db/schema.rb
generated
@ -10,7 +10,7 @@
|
|||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema[8.0].define(version: 2025_03_26_162920) do
|
ActiveRecord::Schema[8.0].define(version: 2025_03_27_111835) do
|
||||||
create_table "active_storage_attachments", force: :cascade do |t|
|
create_table "active_storage_attachments", force: :cascade do |t|
|
||||||
t.string "name", null: false
|
t.string "name", null: false
|
||||||
t.string "record_type", null: false
|
t.string "record_type", null: false
|
||||||
@ -111,6 +111,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_03_26_162920) do
|
|||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
t.string "username"
|
t.string "username"
|
||||||
t.boolean "admin", default: false, null: false
|
t.boolean "admin", default: false, null: false
|
||||||
|
t.string "lang", default: "en"
|
||||||
t.index ["email_address"], name: "index_users_on_email_address", unique: true
|
t.index ["email_address"], name: "index_users_on_email_address", unique: true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,3 +1,25 @@
|
|||||||
|
# == Schema Information
|
||||||
|
#
|
||||||
|
# Table name: contests
|
||||||
|
#
|
||||||
|
# id :integer not null, primary key
|
||||||
|
# allow_registration :boolean default(FALSE)
|
||||||
|
# name :string
|
||||||
|
# slug :string
|
||||||
|
# team :boolean default(FALSE)
|
||||||
|
# created_at :datetime not null
|
||||||
|
# updated_at :datetime not null
|
||||||
|
# user_id :integer not null
|
||||||
|
#
|
||||||
|
# Indexes
|
||||||
|
#
|
||||||
|
# index_contests_on_slug (slug) UNIQUE
|
||||||
|
# index_contests_on_user_id (user_id)
|
||||||
|
#
|
||||||
|
# Foreign Keys
|
||||||
|
#
|
||||||
|
# user_id (user_id => users.id)
|
||||||
|
#
|
||||||
FactoryBot.define do
|
FactoryBot.define do
|
||||||
factory :contest do
|
factory :contest do
|
||||||
name { Faker::Company.unique.name }
|
name { Faker::Company.unique.name }
|
||||||
|
@ -1,3 +1,20 @@
|
|||||||
|
# == Schema Information
|
||||||
|
#
|
||||||
|
# Table name: users
|
||||||
|
#
|
||||||
|
# id :integer not null, primary key
|
||||||
|
# admin :boolean default(FALSE), not null
|
||||||
|
# email_address :string not null
|
||||||
|
# lang :string default("en")
|
||||||
|
# password_digest :string not null
|
||||||
|
# username :string
|
||||||
|
# created_at :datetime not null
|
||||||
|
# updated_at :datetime not null
|
||||||
|
#
|
||||||
|
# Indexes
|
||||||
|
#
|
||||||
|
# index_users_on_email_address (email_address) UNIQUE
|
||||||
|
#
|
||||||
FactoryBot.define do
|
FactoryBot.define do
|
||||||
factory :user do
|
factory :user do
|
||||||
username { Faker::Internet.unique.username }
|
username { Faker::Internet.unique.username }
|
||||||
|
@ -1,3 +1,20 @@
|
|||||||
|
# == Schema Information
|
||||||
|
#
|
||||||
|
# Table name: users
|
||||||
|
#
|
||||||
|
# id :integer not null, primary key
|
||||||
|
# admin :boolean default(FALSE), not null
|
||||||
|
# email_address :string not null
|
||||||
|
# lang :string default("en")
|
||||||
|
# password_digest :string not null
|
||||||
|
# username :string
|
||||||
|
# created_at :datetime not null
|
||||||
|
# updated_at :datetime not null
|
||||||
|
#
|
||||||
|
# Indexes
|
||||||
|
#
|
||||||
|
# index_users_on_email_address (email_address) UNIQUE
|
||||||
|
#
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe User, type: :model do
|
RSpec.describe User, type: :model do
|
||||||
|
1
test/fixtures/users.yml
vendored
1
test/fixtures/users.yml
vendored
@ -8,6 +8,7 @@
|
|||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
# admin :boolean default(FALSE), not null
|
# admin :boolean default(FALSE), not null
|
||||||
# email_address :string not null
|
# email_address :string not null
|
||||||
|
# lang :string default("en")
|
||||||
# password_digest :string not null
|
# password_digest :string not null
|
||||||
# username :string
|
# username :string
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
# id :integer not null, primary key
|
# id :integer not null, primary key
|
||||||
# admin :boolean default(FALSE), not null
|
# admin :boolean default(FALSE), not null
|
||||||
# email_address :string not null
|
# email_address :string not null
|
||||||
|
# lang :string default("en")
|
||||||
# password_digest :string not null
|
# password_digest :string not null
|
||||||
# username :string
|
# username :string
|
||||||
# created_at :datetime not null
|
# created_at :datetime not null
|
||||||
|
Loading…
x
Reference in New Issue
Block a user