diff --git a/Gemfile b/Gemfile
index 2a9aa8721d..9736ddfc20 100644
--- a/Gemfile
+++ b/Gemfile
@@ -90,6 +90,8 @@ gem 'devise'
# An invitation strategy for Devise (https://github.com/scambra/devise_invitable)
gem 'devise_invitable'
+gem 'doorkeeper'
+
# A generalized Rack framework for multiple-provider authentication.
# (https://github.com/omniauth/omniauth)
gem 'omniauth'
diff --git a/Gemfile.lock b/Gemfile.lock
index 56db857b5c..f118b37ca9 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,723 +1,731 @@
-GEM
- remote: https://rubygems.org/
- specs:
- actioncable (7.1.5.2)
- actionpack (= 7.1.5.2)
- activesupport (= 7.1.5.2)
- nio4r (~> 2.0)
- websocket-driver (>= 0.6.1)
- zeitwerk (~> 2.6)
- actionmailbox (7.1.5.2)
- actionpack (= 7.1.5.2)
- activejob (= 7.1.5.2)
- activerecord (= 7.1.5.2)
- activestorage (= 7.1.5.2)
- activesupport (= 7.1.5.2)
- mail (>= 2.7.1)
- net-imap
- net-pop
- net-smtp
- actionmailer (7.1.5.2)
- actionpack (= 7.1.5.2)
- actionview (= 7.1.5.2)
- activejob (= 7.1.5.2)
- activesupport (= 7.1.5.2)
- mail (~> 2.5, >= 2.5.4)
- net-imap
- net-pop
- net-smtp
- rails-dom-testing (~> 2.2)
- actionpack (7.1.5.2)
- actionview (= 7.1.5.2)
- activesupport (= 7.1.5.2)
- nokogiri (>= 1.8.5)
- racc
- rack (>= 2.2.4)
- rack-session (>= 1.0.1)
- rack-test (>= 0.6.3)
- rails-dom-testing (~> 2.2)
- rails-html-sanitizer (~> 1.6)
- actiontext (7.1.5.2)
- actionpack (= 7.1.5.2)
- activerecord (= 7.1.5.2)
- activestorage (= 7.1.5.2)
- activesupport (= 7.1.5.2)
- globalid (>= 0.6.0)
- nokogiri (>= 1.8.5)
- actionview (7.1.5.2)
- activesupport (= 7.1.5.2)
- builder (~> 3.1)
- erubi (~> 1.11)
- rails-dom-testing (~> 2.2)
- rails-html-sanitizer (~> 1.6)
- activejob (7.1.5.2)
- activesupport (= 7.1.5.2)
- globalid (>= 0.3.6)
- activemodel (7.1.5.2)
- activesupport (= 7.1.5.2)
- activerecord (7.1.5.2)
- activemodel (= 7.1.5.2)
- activesupport (= 7.1.5.2)
- timeout (>= 0.4.0)
- activerecord_json_validator (3.1.0)
- activerecord (>= 4.2.0, < 9)
- json_schemer (~> 2.2)
- activestorage (7.1.5.2)
- actionpack (= 7.1.5.2)
- activejob (= 7.1.5.2)
- activerecord (= 7.1.5.2)
- activesupport (= 7.1.5.2)
- marcel (~> 1.0)
- activesupport (7.1.5.2)
- base64
- benchmark (>= 0.3)
- bigdecimal
- concurrent-ruby (~> 1.0, >= 1.0.2)
- connection_pool (>= 2.2.5)
- drb
- i18n (>= 1.6, < 2)
- logger (>= 1.4.2)
- minitest (>= 5.1)
- mutex_m
- securerandom (>= 0.3)
- tzinfo (~> 2.0)
- addressable (2.8.7)
- public_suffix (>= 2.0.2, < 7.0)
- annotate (3.2.0)
- activerecord (>= 3.2, < 8.0)
- rake (>= 10.4, < 14.0)
- annotate_gem (0.0.14)
- bundler (>= 1.1)
- api-pagination (6.0.0)
- ast (2.4.3)
- autoprefixer-rails (10.4.21.0)
- execjs (~> 2)
- base64 (0.3.0)
- bcrypt (3.1.20)
- benchmark (0.4.1)
- better_errors (2.10.1)
- erubi (>= 1.0.0)
- rack (>= 0.9.0)
- rouge (>= 1.0.0)
- bigdecimal (3.3.0)
- bindex (0.8.1)
- binding_of_caller (1.0.1)
- debug_inspector (>= 1.2.0)
- bootsnap (1.18.6)
- msgpack (~> 1.2)
- brakeman (7.1.0)
- racc
- builder (3.3.0)
- bullet (8.0.8)
- activesupport (>= 3.0.0)
- uniform_notifier (~> 1.11)
- bundle-audit (0.1.0)
- bundler-audit
- bundler-audit (0.9.2)
- bundler (>= 1.2.0, < 3)
- thor (~> 1.0)
- byebug (12.0.0)
- capybara (3.40.0)
- addressable
- matrix
- mini_mime (>= 0.1.3)
- nokogiri (~> 1.11)
- rack (>= 1.6.0)
- rack-test (>= 0.6.3)
- regexp_parser (>= 1.5, < 3.0)
- xpath (~> 3.2)
- cgi (0.5.0)
- claide (1.1.0)
- claide-plugins (0.9.2)
- cork
- nap
- open4 (~> 1.3)
- coderay (1.1.3)
- colored2 (3.1.2)
- concurrent-ruby (1.3.5)
- connection_pool (2.5.4)
- contact_us (1.2.0)
- rails (>= 4.2.0)
- cork (0.3.0)
- colored2 (~> 3.1)
- crack (1.0.0)
- bigdecimal
- rexml
- crass (1.0.6)
- cssbundling-rails (1.4.3)
- railties (>= 6.0.0)
- csv (3.3.5)
- danger (9.5.3)
- base64 (~> 0.2)
- claide (~> 1.0)
- claide-plugins (>= 0.9.2)
- colored2 (>= 3.1, < 5)
- cork (~> 0.1)
- faraday (>= 0.9.0, < 3.0)
- faraday-http-cache (~> 2.0)
- git (>= 1.13, < 3.0)
- kramdown (>= 2.5.1, < 3.0)
- kramdown-parser-gfm (~> 1.0)
- octokit (>= 4.0)
- pstore (~> 0.1)
- terminal-table (>= 1, < 5)
- database_cleaner (2.1.0)
- database_cleaner-active_record (>= 2, < 3)
- database_cleaner-active_record (2.2.2)
- activerecord (>= 5.a)
- database_cleaner-core (~> 2.0)
- database_cleaner-core (2.0.1)
- date (3.4.1)
- debug_inspector (1.2.0)
- devise (4.9.4)
- bcrypt (~> 3.0)
- orm_adapter (~> 0.1)
- railties (>= 4.1.0)
- responders
- warden (~> 1.2.3)
- devise_invitable (2.0.11)
- actionmailer (>= 5.0)
- devise (>= 4.6)
- diff-lcs (1.6.2)
- dotenv (3.1.8)
- dotenv-rails (3.1.8)
- dotenv (= 3.1.8)
- railties (>= 6.1)
- dragonfly (1.4.1)
- addressable (~> 2.3)
- multi_json (~> 1.0)
- ostruct (~> 0.6.1)
- rack (>= 1.3)
- dragonfly-s3_data_store (1.3.0)
- dragonfly (~> 1.0)
- fog-aws
- drb (2.2.3)
- erb (4.0.4)
- cgi (>= 0.3.3)
- erubi (1.13.1)
- excon (1.3.0)
- logger
- execjs (2.10.0)
- factory_bot (6.5.5)
- activesupport (>= 6.1.0)
- factory_bot_rails (6.5.1)
- factory_bot (~> 6.5)
- railties (>= 6.1.0)
- faker (3.5.2)
- i18n (>= 1.8.11, < 2)
- faraday (2.14.0)
- faraday-net_http (>= 2.0, < 3.5)
- json
- logger
- faraday-http-cache (2.5.1)
- faraday (>= 0.8)
- faraday-net_http (3.4.1)
- net-http (>= 0.5.0)
- ffi (1.17.2-arm64-darwin)
- ffi (1.17.2-x86_64-linux-gnu)
- flag_shih_tzu (0.3.23)
- fog-aws (3.33.0)
- base64 (>= 0.2, < 0.4)
- fog-core (~> 2.6)
- fog-json (~> 1.1)
- fog-xml (~> 0.1)
- fog-core (2.6.0)
- builder
- excon (~> 1.0)
- formatador (>= 0.2, < 2.0)
- mime-types
- fog-json (1.2.0)
- fog-core
- multi_json (~> 1.10)
- fog-xml (0.1.5)
- fog-core
- nokogiri (>= 1.5.11, < 2.0.0)
- formatador (1.2.1)
- reline
- forwardable (1.3.3)
- fuubar (2.5.1)
- rspec-core (~> 3.0)
- ruby-progressbar (~> 1.4)
- gettext (3.4.9)
- erubi
- locale (>= 2.0.5)
- prime
- racc
- text (>= 1.3.0)
- git (2.3.3)
- activesupport (>= 5.0)
- addressable (~> 2.8)
- process_executer (~> 1.1)
- rchardet (~> 1.8)
- globalid (1.3.0)
- activesupport (>= 6.1)
- guard (2.19.1)
- formatador (>= 0.2.4)
- listen (>= 2.7, < 4.0)
- logger (~> 1.6)
- lumberjack (>= 1.0.12, < 2.0)
- nenv (~> 0.1)
- notiffany (~> 0.0)
- ostruct (~> 0.6)
- pry (>= 0.13.0)
- shellany (~> 0.0)
- thor (>= 0.18.1)
- hana (1.3.7)
- hashdiff (1.2.1)
- hashie (5.0.0)
- highline (3.1.2)
- reline
- htmltoword (1.1.1)
- actionpack
- nokogiri
- rubyzip (>= 1.0)
- httparty (0.23.1)
- csv
- mini_mime (>= 1.0.0)
- multi_xml (>= 0.5.2)
- i18n (1.14.7)
- concurrent-ruby (~> 1.0)
- io-console (0.8.1)
- irb (1.15.2)
- pp (>= 0.6.0)
- rdoc (>= 4.0.0)
- reline (>= 0.4.2)
- jbuilder (2.14.1)
- actionview (>= 7.0.0)
- activesupport (>= 7.0.0)
- jsbundling-rails (1.3.1)
- railties (>= 6.0.0)
- json (2.15.1)
- json_schemer (2.4.0)
- bigdecimal
- hana (~> 1.3)
- regexp_parser (~> 2.0)
- simpleidn (~> 0.2)
- jwt (3.1.2)
- base64
- kaminari (1.2.2)
- activesupport (>= 4.1.0)
- kaminari-actionview (= 1.2.2)
- kaminari-activerecord (= 1.2.2)
- kaminari-core (= 1.2.2)
- kaminari-actionview (1.2.2)
- actionview
- kaminari-core (= 1.2.2)
- kaminari-activerecord (1.2.2)
- activerecord
- kaminari-core (= 1.2.2)
- kaminari-core (1.2.2)
- kramdown (2.5.1)
- rexml (>= 3.3.9)
- kramdown-parser-gfm (1.1.0)
- kramdown (~> 2.0)
- language_server-protocol (3.17.0.5)
- ledermann-rails-settings (2.6.2)
- activerecord (>= 6.1)
- lint_roller (1.1.0)
- listen (3.9.0)
- rb-fsevent (~> 0.10, >= 0.10.3)
- rb-inotify (~> 0.9, >= 0.9.10)
- locale (2.1.4)
- logger (1.7.0)
- loofah (2.24.1)
- crass (~> 1.0.2)
- nokogiri (>= 1.12.0)
- lumberjack (1.4.2)
- mail (2.7.1)
- mini_mime (>= 0.1.1)
- marcel (1.1.0)
- matrix (0.4.3)
- method_source (1.1.0)
- mime-types (3.7.0)
- logger
- mime-types-data (~> 3.2025, >= 3.2025.0507)
- mime-types-data (3.2025.0924)
- mimemagic (0.4.3)
- nokogiri (~> 1)
- rake
- mini_mime (1.1.5)
- minitest (5.25.5)
- mocha (2.7.1)
- ruby2_keywords (>= 0.0.5)
- msgpack (1.8.0)
- multi_json (1.17.0)
- multi_xml (0.7.1)
- bigdecimal (~> 3.1)
- mutex_m (0.3.0)
- mysql2 (0.5.7)
- bigdecimal
- nap (1.1.0)
- nenv (0.3.0)
- net-http (0.6.0)
- uri
- net-imap (0.5.12)
- date
- net-protocol
- net-pop (0.1.2)
- net-protocol
- net-protocol (0.2.2)
- timeout
- net-smtp (0.5.1)
- net-protocol
- nio4r (2.7.4)
- nokogiri (1.18.10-arm64-darwin)
- racc (~> 1.4)
- nokogiri (1.18.10-x86_64-linux-gnu)
- racc (~> 1.4)
- notiffany (0.1.3)
- nenv (~> 0.1)
- shellany (~> 0.0)
- oauth2 (2.0.17)
- faraday (>= 0.17.3, < 4.0)
- jwt (>= 1.0, < 4.0)
- logger (~> 1.2)
- multi_xml (~> 0.5)
- rack (>= 1.2, < 4)
- snaky_hash (~> 2.0, >= 2.0.3)
- version_gem (~> 1.1, >= 1.1.9)
- octokit (10.0.0)
- faraday (>= 1, < 3)
- sawyer (~> 0.9)
- omniauth (2.1.4)
- hashie (>= 3.4.6)
- logger
- rack (>= 2.2.3)
- rack-protection
- omniauth-oauth2 (1.8.0)
- oauth2 (>= 1.4, < 3)
- omniauth (~> 2.0)
- omniauth-orcid (2.1.1)
- omniauth-oauth2 (~> 1.3)
- ruby_dig (~> 0.0.2)
- omniauth-rails_csrf_protection (1.0.2)
- actionpack (>= 4.2)
- omniauth (~> 2.0)
- omniauth-shibboleth (1.3.0)
- omniauth (>= 1.0.0)
- open4 (1.3.4)
- options (2.3.2)
- orm_adapter (0.5.0)
- ostruct (0.6.3)
- parallel (1.27.0)
- parser (3.3.9.0)
- ast (~> 2.4.1)
- racc
- pg (1.6.2-arm64-darwin)
- pg (1.6.2-x86_64-linux)
- pp (0.6.3)
- prettyprint
- prettyprint (0.2.0)
- prime (0.1.4)
- forwardable
- singleton
- prism (1.5.1)
- process_executer (1.3.0)
- progress_bar (1.3.4)
- highline (>= 1.6)
- options (~> 2.3.0)
- pry (0.15.2)
- coderay (~> 1.1)
- method_source (~> 1.0)
- pstore (0.2.0)
- psych (5.2.6)
- date
- stringio
- public_suffix (6.0.2)
- puma (7.0.4)
- nio4r (~> 2.0)
- pundit (2.5.2)
- activesupport (>= 3.0.0)
- pundit-matchers (4.0.0)
- rspec-core (~> 3.12)
- rspec-expectations (~> 3.12)
- rspec-mocks (~> 3.12)
- rspec-support (~> 3.12)
- racc (1.8.1)
- rack (3.2.2)
- rack-attack (6.7.0)
- rack (>= 1.0, < 4)
- rack-mini-profiler (4.0.1)
- rack (>= 1.2.0)
- rack-protection (4.1.1)
- base64 (>= 0.1.0)
- logger (>= 1.6.0)
- rack (>= 3.0.0, < 4)
- rack-session (2.1.1)
- base64 (>= 0.1.0)
- rack (>= 3.0.0)
- rack-test (2.2.0)
- rack (>= 1.3)
- rackup (2.2.1)
- rack (>= 3)
- rails (7.1.5.2)
- actioncable (= 7.1.5.2)
- actionmailbox (= 7.1.5.2)
- actionmailer (= 7.1.5.2)
- actionpack (= 7.1.5.2)
- actiontext (= 7.1.5.2)
- actionview (= 7.1.5.2)
- activejob (= 7.1.5.2)
- activemodel (= 7.1.5.2)
- activerecord (= 7.1.5.2)
- activestorage (= 7.1.5.2)
- activesupport (= 7.1.5.2)
- bundler (>= 1.15.0)
- railties (= 7.1.5.2)
- rails-controller-testing (1.0.5)
- actionpack (>= 5.0.1.rc1)
- actionview (>= 5.0.1.rc1)
- activesupport (>= 5.0.1.rc1)
- rails-dom-testing (2.3.0)
- activesupport (>= 5.0.0)
- minitest
- nokogiri (>= 1.6)
- rails-html-sanitizer (1.6.2)
- loofah (~> 2.21)
- nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
- railties (7.1.5.2)
- actionpack (= 7.1.5.2)
- activesupport (= 7.1.5.2)
- irb
- rackup (>= 1.0.0)
- rake (>= 12.2)
- thor (~> 1.0, >= 1.2.2)
- zeitwerk (~> 2.6)
- rainbow (3.1.1)
- rake (13.3.0)
- rb-fsevent (0.11.2)
- rb-inotify (0.11.1)
- ffi (~> 1.0)
- rchardet (1.10.0)
- rdoc (6.15.0)
- erb
- psych (>= 4.0.0)
- tsort
- recaptcha (5.21.1)
- regexp_parser (2.11.3)
- reline (0.6.2)
- io-console (~> 0.5)
- responders (3.1.1)
- actionpack (>= 5.2)
- railties (>= 5.2)
- rexml (3.4.4)
- rollbar (3.6.2)
- rouge (4.6.1)
- rspec-collection_matchers (1.2.1)
- rspec-expectations (>= 2.99.0.beta1)
- rspec-core (3.13.5)
- rspec-support (~> 3.13.0)
- rspec-expectations (3.13.5)
- diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.13.0)
- rspec-mocks (3.13.5)
- diff-lcs (>= 1.2.0, < 2.0)
- rspec-support (~> 3.13.0)
- rspec-rails (7.1.1)
- actionpack (>= 7.0)
- activesupport (>= 7.0)
- railties (>= 7.0)
- rspec-core (~> 3.13)
- rspec-expectations (~> 3.13)
- rspec-mocks (~> 3.13)
- rspec-support (~> 3.13)
- rspec-support (3.13.6)
- rubocop (1.81.1)
- json (~> 2.3)
- language_server-protocol (~> 3.17.0.2)
- lint_roller (~> 1.1.0)
- parallel (~> 1.10)
- parser (>= 3.3.0.2)
- rainbow (>= 2.2.2, < 4.0)
- regexp_parser (>= 2.9.3, < 3.0)
- rubocop-ast (>= 1.47.1, < 2.0)
- ruby-progressbar (~> 1.7)
- unicode-display_width (>= 2.4.0, < 4.0)
- rubocop-ast (1.47.1)
- parser (>= 3.3.7.2)
- prism (~> 1.4)
- rubocop-i18n (3.2.3)
- lint_roller (~> 1.1)
- rubocop (>= 1.72.1)
- rubocop-performance (1.26.0)
- lint_roller (~> 1.1)
- rubocop (>= 1.75.0, < 2.0)
- rubocop-ast (>= 1.44.0, < 2.0)
- ruby-progressbar (1.13.0)
- ruby2_keywords (0.0.5)
- ruby_dig (0.0.2)
- rubyzip (2.4.1)
- sawyer (0.9.2)
- addressable (>= 2.3.5)
- faraday (>= 0.17.3, < 3)
- securerandom (0.4.1)
- selenium-webdriver (4.32.0)
- base64 (~> 0.2)
- logger (~> 1.4)
- rexml (~> 3.2, >= 3.2.5)
- rubyzip (>= 1.2.2, < 3.0)
- websocket (~> 1.0)
- shellany (0.0.1)
- shoulda (4.0.0)
- shoulda-context (~> 2.0)
- shoulda-matchers (~> 4.0)
- shoulda-context (2.0.0)
- shoulda-matchers (4.5.1)
- activesupport (>= 4.2.0)
- simpleidn (0.2.3)
- singleton (0.3.0)
- snaky_hash (2.0.3)
- hashie (>= 0.1.0, < 6)
- version_gem (>= 1.1.8, < 3)
- spring (4.4.0)
- spring-commands-rspec (1.0.4)
- spring (>= 0.9.1)
- spring-watcher-listen (2.1.0)
- listen (>= 2.7, < 4.0)
- spring (>= 4)
- sprockets (4.2.2)
- concurrent-ruby (~> 1.0)
- logger
- rack (>= 2.2.4, < 4)
- sprockets-rails (3.5.2)
- actionpack (>= 6.1)
- activesupport (>= 6.1)
- sprockets (>= 3.0.0)
- stringio (3.1.7)
- terminal-table (4.0.0)
- unicode-display_width (>= 1.1.1, < 4)
- text (1.3.1)
- thor (1.4.0)
- timeout (0.4.3)
- tomparse (0.4.2)
- translation (1.41)
- gettext (~> 3.2, >= 3.2.5, <= 3.4.9)
- tsort (0.2.0)
- turbo-rails (2.0.17)
- actionpack (>= 7.1.0)
- railties (>= 7.1.0)
- tzinfo (2.0.6)
- concurrent-ruby (~> 1.0)
- unicode-display_width (3.2.0)
- unicode-emoji (~> 4.1)
- unicode-emoji (4.1.0)
- uniform_notifier (1.18.0)
- uri (1.0.4)
- version_gem (1.1.9)
- warden (1.2.9)
- rack (>= 2.0.9)
- web-console (4.2.1)
- actionview (>= 6.0.0)
- activemodel (>= 6.0.0)
- bindex (>= 0.4.0)
- railties (>= 6.0.0)
- webmock (3.25.1)
- addressable (>= 2.8.0)
- crack (>= 0.3.2)
- hashdiff (>= 0.4.0, < 2.0.0)
- websocket (1.2.11)
- websocket-driver (0.8.0)
- base64
- websocket-extensions (>= 0.1.0)
- websocket-extensions (0.1.5)
- wicked_pdf (2.8.2)
- activesupport
- ostruct
- wkhtmltopdf-binary (0.12.6.10)
- xpath (3.2.0)
- nokogiri (~> 1.8)
- yard (0.9.37)
- yard-tomdoc (0.7.1)
- tomparse (>= 0.4.0)
- yard
- zeitwerk (2.6.18)
-
-PLATFORMS
- arm64-darwin-21
- arm64-darwin-22
- x86_64-linux
-
-DEPENDENCIES
- activerecord_json_validator
- annotate
- annotate_gem
- api-pagination
- autoprefixer-rails
- better_errors
- binding_of_caller
- bootsnap
- brakeman
- bullet
- bundle-audit
- byebug
- capybara
- contact_us
- cssbundling-rails
- danger
- database_cleaner
- devise
- devise_invitable
- dotenv-rails
- dragonfly
- dragonfly-s3_data_store
- factory_bot_rails
- faker
- flag_shih_tzu
- fuubar
- guard
- htmltoword
- httparty
- jbuilder
- jsbundling-rails
- jwt
- kaminari
- ledermann-rails-settings
- listen
- mail (= 2.7.1)
- mimemagic
- mocha
- mysql2
- net-smtp
- omniauth
- omniauth-orcid
- omniauth-rails_csrf_protection
- omniauth-shibboleth
- parallel
- pg
- progress_bar
- puma
- pundit
- pundit-matchers
- rack-attack (~> 6.6, >= 6.6.1)
- rack-mini-profiler
- rails (~> 7.1)
- rails-controller-testing
- recaptcha
- rollbar
- rspec-collection_matchers
- rspec-rails
- rubocop
- rubocop-i18n
- rubocop-performance
- ruby-progressbar
- selenium-webdriver
- shoulda
- spring
- spring-commands-rspec
- spring-watcher-listen
- sprockets-rails
- text
- translation
- turbo-rails
- web-console
- webmock
- wicked_pdf
- wkhtmltopdf-binary
- yard
- yard-tomdoc
-
-RUBY VERSION
- ruby 3.1.4p223
-
-BUNDLED WITH
- 2.4.17
+GEM
+ remote: https://rubygems.org/
+ specs:
+ actioncable (7.1.5.2)
+ actionpack (= 7.1.5.2)
+ activesupport (= 7.1.5.2)
+ nio4r (~> 2.0)
+ websocket-driver (>= 0.6.1)
+ zeitwerk (~> 2.6)
+ actionmailbox (7.1.5.2)
+ actionpack (= 7.1.5.2)
+ activejob (= 7.1.5.2)
+ activerecord (= 7.1.5.2)
+ activestorage (= 7.1.5.2)
+ activesupport (= 7.1.5.2)
+ mail (>= 2.7.1)
+ net-imap
+ net-pop
+ net-smtp
+ actionmailer (7.1.5.2)
+ actionpack (= 7.1.5.2)
+ actionview (= 7.1.5.2)
+ activejob (= 7.1.5.2)
+ activesupport (= 7.1.5.2)
+ mail (~> 2.5, >= 2.5.4)
+ net-imap
+ net-pop
+ net-smtp
+ rails-dom-testing (~> 2.2)
+ actionpack (7.1.5.2)
+ actionview (= 7.1.5.2)
+ activesupport (= 7.1.5.2)
+ nokogiri (>= 1.8.5)
+ racc
+ rack (>= 2.2.4)
+ rack-session (>= 1.0.1)
+ rack-test (>= 0.6.3)
+ rails-dom-testing (~> 2.2)
+ rails-html-sanitizer (~> 1.6)
+ actiontext (7.1.5.2)
+ actionpack (= 7.1.5.2)
+ activerecord (= 7.1.5.2)
+ activestorage (= 7.1.5.2)
+ activesupport (= 7.1.5.2)
+ globalid (>= 0.6.0)
+ nokogiri (>= 1.8.5)
+ actionview (7.1.5.2)
+ activesupport (= 7.1.5.2)
+ builder (~> 3.1)
+ erubi (~> 1.11)
+ rails-dom-testing (~> 2.2)
+ rails-html-sanitizer (~> 1.6)
+ activejob (7.1.5.2)
+ activesupport (= 7.1.5.2)
+ globalid (>= 0.3.6)
+ activemodel (7.1.5.2)
+ activesupport (= 7.1.5.2)
+ activerecord (7.1.5.2)
+ activemodel (= 7.1.5.2)
+ activesupport (= 7.1.5.2)
+ timeout (>= 0.4.0)
+ activerecord_json_validator (3.1.0)
+ activerecord (>= 4.2.0, < 9)
+ json_schemer (~> 2.2)
+ activestorage (7.1.5.2)
+ actionpack (= 7.1.5.2)
+ activejob (= 7.1.5.2)
+ activerecord (= 7.1.5.2)
+ activesupport (= 7.1.5.2)
+ marcel (~> 1.0)
+ activesupport (7.1.5.2)
+ base64
+ benchmark (>= 0.3)
+ bigdecimal
+ concurrent-ruby (~> 1.0, >= 1.0.2)
+ connection_pool (>= 2.2.5)
+ drb
+ i18n (>= 1.6, < 2)
+ logger (>= 1.4.2)
+ minitest (>= 5.1)
+ mutex_m
+ securerandom (>= 0.3)
+ tzinfo (~> 2.0)
+ addressable (2.8.7)
+ public_suffix (>= 2.0.2, < 7.0)
+ annotate (3.2.0)
+ activerecord (>= 3.2, < 8.0)
+ rake (>= 10.4, < 14.0)
+ annotate_gem (0.0.14)
+ bundler (>= 1.1)
+ api-pagination (6.0.0)
+ ast (2.4.3)
+ autoprefixer-rails (10.4.21.0)
+ execjs (~> 2)
+ base64 (0.3.0)
+ bcrypt (3.1.20)
+ benchmark (0.4.1)
+ better_errors (2.10.1)
+ erubi (>= 1.0.0)
+ rack (>= 0.9.0)
+ rouge (>= 1.0.0)
+ bigdecimal (3.3.0)
+ bindex (0.8.1)
+ binding_of_caller (1.0.1)
+ debug_inspector (>= 1.2.0)
+ bootsnap (1.18.6)
+ msgpack (~> 1.2)
+ brakeman (7.1.0)
+ racc
+ builder (3.3.0)
+ bullet (8.0.8)
+ activesupport (>= 3.0.0)
+ uniform_notifier (~> 1.11)
+ bundle-audit (0.1.0)
+ bundler-audit
+ bundler-audit (0.9.2)
+ bundler (>= 1.2.0, < 3)
+ thor (~> 1.0)
+ byebug (12.0.0)
+ capybara (3.40.0)
+ addressable
+ matrix
+ mini_mime (>= 0.1.3)
+ nokogiri (~> 1.11)
+ rack (>= 1.6.0)
+ rack-test (>= 0.6.3)
+ regexp_parser (>= 1.5, < 3.0)
+ xpath (~> 3.2)
+ cgi (0.5.0)
+ claide (1.1.0)
+ claide-plugins (0.9.2)
+ cork
+ nap
+ open4 (~> 1.3)
+ coderay (1.1.3)
+ colored2 (3.1.2)
+ concurrent-ruby (1.3.5)
+ connection_pool (2.5.4)
+ contact_us (1.2.0)
+ rails (>= 4.2.0)
+ cork (0.3.0)
+ colored2 (~> 3.1)
+ crack (1.0.0)
+ bigdecimal
+ rexml
+ crass (1.0.6)
+ cssbundling-rails (1.4.3)
+ railties (>= 6.0.0)
+ csv (3.3.5)
+ danger (9.5.3)
+ base64 (~> 0.2)
+ claide (~> 1.0)
+ claide-plugins (>= 0.9.2)
+ colored2 (>= 3.1, < 5)
+ cork (~> 0.1)
+ faraday (>= 0.9.0, < 3.0)
+ faraday-http-cache (~> 2.0)
+ git (>= 1.13, < 3.0)
+ kramdown (>= 2.5.1, < 3.0)
+ kramdown-parser-gfm (~> 1.0)
+ octokit (>= 4.0)
+ pstore (~> 0.1)
+ terminal-table (>= 1, < 5)
+ database_cleaner (2.1.0)
+ database_cleaner-active_record (>= 2, < 3)
+ database_cleaner-active_record (2.2.2)
+ activerecord (>= 5.a)
+ database_cleaner-core (~> 2.0)
+ database_cleaner-core (2.0.1)
+ date (3.4.1)
+ debug_inspector (1.2.0)
+ devise (4.9.4)
+ bcrypt (~> 3.0)
+ orm_adapter (~> 0.1)
+ railties (>= 4.1.0)
+ responders
+ warden (~> 1.2.3)
+ devise_invitable (2.0.11)
+ actionmailer (>= 5.0)
+ devise (>= 4.6)
+ diff-lcs (1.6.2)
+ doorkeeper (5.8.2)
+ railties (>= 5)
+ dotenv (3.1.8)
+ dotenv-rails (3.1.8)
+ dotenv (= 3.1.8)
+ railties (>= 6.1)
+ dragonfly (1.4.1)
+ addressable (~> 2.3)
+ multi_json (~> 1.0)
+ ostruct (~> 0.6.1)
+ rack (>= 1.3)
+ dragonfly-s3_data_store (1.3.0)
+ dragonfly (~> 1.0)
+ fog-aws
+ drb (2.2.3)
+ erb (4.0.4)
+ cgi (>= 0.3.3)
+ erubi (1.13.1)
+ excon (1.3.0)
+ logger
+ execjs (2.10.0)
+ factory_bot (6.5.5)
+ activesupport (>= 6.1.0)
+ factory_bot_rails (6.5.1)
+ factory_bot (~> 6.5)
+ railties (>= 6.1.0)
+ faker (3.5.2)
+ i18n (>= 1.8.11, < 2)
+ faraday (2.14.0)
+ faraday-net_http (>= 2.0, < 3.5)
+ json
+ logger
+ faraday-http-cache (2.5.1)
+ faraday (>= 0.8)
+ faraday-net_http (3.4.1)
+ net-http (>= 0.5.0)
+ ffi (1.17.2-aarch64-linux-gnu)
+ ffi (1.17.2-arm64-darwin)
+ ffi (1.17.2-x86_64-linux-gnu)
+ flag_shih_tzu (0.3.23)
+ fog-aws (3.33.0)
+ base64 (>= 0.2, < 0.4)
+ fog-core (~> 2.6)
+ fog-json (~> 1.1)
+ fog-xml (~> 0.1)
+ fog-core (2.6.0)
+ builder
+ excon (~> 1.0)
+ formatador (>= 0.2, < 2.0)
+ mime-types
+ fog-json (1.2.0)
+ fog-core
+ multi_json (~> 1.10)
+ fog-xml (0.1.5)
+ fog-core
+ nokogiri (>= 1.5.11, < 2.0.0)
+ formatador (1.2.1)
+ reline
+ forwardable (1.3.3)
+ fuubar (2.5.1)
+ rspec-core (~> 3.0)
+ ruby-progressbar (~> 1.4)
+ gettext (3.4.9)
+ erubi
+ locale (>= 2.0.5)
+ prime
+ racc
+ text (>= 1.3.0)
+ git (2.3.3)
+ activesupport (>= 5.0)
+ addressable (~> 2.8)
+ process_executer (~> 1.1)
+ rchardet (~> 1.8)
+ globalid (1.3.0)
+ activesupport (>= 6.1)
+ guard (2.19.1)
+ formatador (>= 0.2.4)
+ listen (>= 2.7, < 4.0)
+ logger (~> 1.6)
+ lumberjack (>= 1.0.12, < 2.0)
+ nenv (~> 0.1)
+ notiffany (~> 0.0)
+ ostruct (~> 0.6)
+ pry (>= 0.13.0)
+ shellany (~> 0.0)
+ thor (>= 0.18.1)
+ hana (1.3.7)
+ hashdiff (1.2.1)
+ hashie (5.0.0)
+ highline (3.1.2)
+ reline
+ htmltoword (1.1.1)
+ actionpack
+ nokogiri
+ rubyzip (>= 1.0)
+ httparty (0.23.1)
+ csv
+ mini_mime (>= 1.0.0)
+ multi_xml (>= 0.5.2)
+ i18n (1.14.7)
+ concurrent-ruby (~> 1.0)
+ io-console (0.8.1)
+ irb (1.15.2)
+ pp (>= 0.6.0)
+ rdoc (>= 4.0.0)
+ reline (>= 0.4.2)
+ jbuilder (2.14.1)
+ actionview (>= 7.0.0)
+ activesupport (>= 7.0.0)
+ jsbundling-rails (1.3.1)
+ railties (>= 6.0.0)
+ json (2.15.1)
+ json_schemer (2.4.0)
+ bigdecimal
+ hana (~> 1.3)
+ regexp_parser (~> 2.0)
+ simpleidn (~> 0.2)
+ jwt (3.1.2)
+ base64
+ kaminari (1.2.2)
+ activesupport (>= 4.1.0)
+ kaminari-actionview (= 1.2.2)
+ kaminari-activerecord (= 1.2.2)
+ kaminari-core (= 1.2.2)
+ kaminari-actionview (1.2.2)
+ actionview
+ kaminari-core (= 1.2.2)
+ kaminari-activerecord (1.2.2)
+ activerecord
+ kaminari-core (= 1.2.2)
+ kaminari-core (1.2.2)
+ kramdown (2.5.1)
+ rexml (>= 3.3.9)
+ kramdown-parser-gfm (1.1.0)
+ kramdown (~> 2.0)
+ language_server-protocol (3.17.0.5)
+ ledermann-rails-settings (2.6.2)
+ activerecord (>= 6.1)
+ lint_roller (1.1.0)
+ listen (3.9.0)
+ rb-fsevent (~> 0.10, >= 0.10.3)
+ rb-inotify (~> 0.9, >= 0.9.10)
+ locale (2.1.4)
+ logger (1.7.0)
+ loofah (2.24.1)
+ crass (~> 1.0.2)
+ nokogiri (>= 1.12.0)
+ lumberjack (1.4.2)
+ mail (2.7.1)
+ mini_mime (>= 0.1.1)
+ marcel (1.1.0)
+ matrix (0.4.3)
+ method_source (1.1.0)
+ mime-types (3.7.0)
+ logger
+ mime-types-data (~> 3.2025, >= 3.2025.0507)
+ mime-types-data (3.2025.0924)
+ mimemagic (0.4.3)
+ nokogiri (~> 1)
+ rake
+ mini_mime (1.1.5)
+ minitest (5.25.5)
+ mocha (2.7.1)
+ ruby2_keywords (>= 0.0.5)
+ msgpack (1.8.0)
+ multi_json (1.17.0)
+ multi_xml (0.7.1)
+ bigdecimal (~> 3.1)
+ mutex_m (0.3.0)
+ mysql2 (0.5.7)
+ bigdecimal
+ nap (1.1.0)
+ nenv (0.3.0)
+ net-http (0.6.0)
+ uri
+ net-imap (0.5.12)
+ date
+ net-protocol
+ net-pop (0.1.2)
+ net-protocol
+ net-protocol (0.2.2)
+ timeout
+ net-smtp (0.5.1)
+ net-protocol
+ nio4r (2.7.4)
+ nokogiri (1.18.10-aarch64-linux-gnu)
+ racc (~> 1.4)
+ nokogiri (1.18.10-arm64-darwin)
+ racc (~> 1.4)
+ nokogiri (1.18.10-x86_64-linux-gnu)
+ racc (~> 1.4)
+ notiffany (0.1.3)
+ nenv (~> 0.1)
+ shellany (~> 0.0)
+ oauth2 (2.0.17)
+ faraday (>= 0.17.3, < 4.0)
+ jwt (>= 1.0, < 4.0)
+ logger (~> 1.2)
+ multi_xml (~> 0.5)
+ rack (>= 1.2, < 4)
+ snaky_hash (~> 2.0, >= 2.0.3)
+ version_gem (~> 1.1, >= 1.1.9)
+ octokit (10.0.0)
+ faraday (>= 1, < 3)
+ sawyer (~> 0.9)
+ omniauth (2.1.4)
+ hashie (>= 3.4.6)
+ logger
+ rack (>= 2.2.3)
+ rack-protection
+ omniauth-oauth2 (1.8.0)
+ oauth2 (>= 1.4, < 3)
+ omniauth (~> 2.0)
+ omniauth-orcid (2.1.1)
+ omniauth-oauth2 (~> 1.3)
+ ruby_dig (~> 0.0.2)
+ omniauth-rails_csrf_protection (1.0.2)
+ actionpack (>= 4.2)
+ omniauth (~> 2.0)
+ omniauth-shibboleth (1.3.0)
+ omniauth (>= 1.0.0)
+ open4 (1.3.4)
+ options (2.3.2)
+ orm_adapter (0.5.0)
+ ostruct (0.6.3)
+ parallel (1.27.0)
+ parser (3.3.9.0)
+ ast (~> 2.4.1)
+ racc
+ pg (1.6.2-aarch64-linux)
+ pg (1.6.2-arm64-darwin)
+ pg (1.6.2-x86_64-linux)
+ pp (0.6.3)
+ prettyprint
+ prettyprint (0.2.0)
+ prime (0.1.4)
+ forwardable
+ singleton
+ prism (1.5.1)
+ process_executer (1.3.0)
+ progress_bar (1.3.4)
+ highline (>= 1.6)
+ options (~> 2.3.0)
+ pry (0.15.2)
+ coderay (~> 1.1)
+ method_source (~> 1.0)
+ pstore (0.2.0)
+ psych (5.2.6)
+ date
+ stringio
+ public_suffix (6.0.2)
+ puma (7.0.4)
+ nio4r (~> 2.0)
+ pundit (2.5.2)
+ activesupport (>= 3.0.0)
+ pundit-matchers (4.0.0)
+ rspec-core (~> 3.12)
+ rspec-expectations (~> 3.12)
+ rspec-mocks (~> 3.12)
+ rspec-support (~> 3.12)
+ racc (1.8.1)
+ rack (3.2.2)
+ rack-attack (6.7.0)
+ rack (>= 1.0, < 4)
+ rack-mini-profiler (4.0.1)
+ rack (>= 1.2.0)
+ rack-protection (4.1.1)
+ base64 (>= 0.1.0)
+ logger (>= 1.6.0)
+ rack (>= 3.0.0, < 4)
+ rack-session (2.1.1)
+ base64 (>= 0.1.0)
+ rack (>= 3.0.0)
+ rack-test (2.2.0)
+ rack (>= 1.3)
+ rackup (2.2.1)
+ rack (>= 3)
+ rails (7.1.5.2)
+ actioncable (= 7.1.5.2)
+ actionmailbox (= 7.1.5.2)
+ actionmailer (= 7.1.5.2)
+ actionpack (= 7.1.5.2)
+ actiontext (= 7.1.5.2)
+ actionview (= 7.1.5.2)
+ activejob (= 7.1.5.2)
+ activemodel (= 7.1.5.2)
+ activerecord (= 7.1.5.2)
+ activestorage (= 7.1.5.2)
+ activesupport (= 7.1.5.2)
+ bundler (>= 1.15.0)
+ railties (= 7.1.5.2)
+ rails-controller-testing (1.0.5)
+ actionpack (>= 5.0.1.rc1)
+ actionview (>= 5.0.1.rc1)
+ activesupport (>= 5.0.1.rc1)
+ rails-dom-testing (2.3.0)
+ activesupport (>= 5.0.0)
+ minitest
+ nokogiri (>= 1.6)
+ rails-html-sanitizer (1.6.2)
+ loofah (~> 2.21)
+ nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
+ railties (7.1.5.2)
+ actionpack (= 7.1.5.2)
+ activesupport (= 7.1.5.2)
+ irb
+ rackup (>= 1.0.0)
+ rake (>= 12.2)
+ thor (~> 1.0, >= 1.2.2)
+ zeitwerk (~> 2.6)
+ rainbow (3.1.1)
+ rake (13.3.0)
+ rb-fsevent (0.11.2)
+ rb-inotify (0.11.1)
+ ffi (~> 1.0)
+ rchardet (1.10.0)
+ rdoc (6.15.0)
+ erb
+ psych (>= 4.0.0)
+ tsort
+ recaptcha (5.21.1)
+ regexp_parser (2.11.3)
+ reline (0.6.2)
+ io-console (~> 0.5)
+ responders (3.1.1)
+ actionpack (>= 5.2)
+ railties (>= 5.2)
+ rexml (3.4.4)
+ rollbar (3.6.2)
+ rouge (4.6.1)
+ rspec-collection_matchers (1.2.1)
+ rspec-expectations (>= 2.99.0.beta1)
+ rspec-core (3.13.5)
+ rspec-support (~> 3.13.0)
+ rspec-expectations (3.13.5)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.13.0)
+ rspec-mocks (3.13.5)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.13.0)
+ rspec-rails (7.1.1)
+ actionpack (>= 7.0)
+ activesupport (>= 7.0)
+ railties (>= 7.0)
+ rspec-core (~> 3.13)
+ rspec-expectations (~> 3.13)
+ rspec-mocks (~> 3.13)
+ rspec-support (~> 3.13)
+ rspec-support (3.13.6)
+ rubocop (1.81.1)
+ json (~> 2.3)
+ language_server-protocol (~> 3.17.0.2)
+ lint_roller (~> 1.1.0)
+ parallel (~> 1.10)
+ parser (>= 3.3.0.2)
+ rainbow (>= 2.2.2, < 4.0)
+ regexp_parser (>= 2.9.3, < 3.0)
+ rubocop-ast (>= 1.47.1, < 2.0)
+ ruby-progressbar (~> 1.7)
+ unicode-display_width (>= 2.4.0, < 4.0)
+ rubocop-ast (1.47.1)
+ parser (>= 3.3.7.2)
+ prism (~> 1.4)
+ rubocop-i18n (3.2.3)
+ lint_roller (~> 1.1)
+ rubocop (>= 1.72.1)
+ rubocop-performance (1.26.0)
+ lint_roller (~> 1.1)
+ rubocop (>= 1.75.0, < 2.0)
+ rubocop-ast (>= 1.44.0, < 2.0)
+ ruby-progressbar (1.13.0)
+ ruby2_keywords (0.0.5)
+ ruby_dig (0.0.2)
+ rubyzip (2.4.1)
+ sawyer (0.9.2)
+ addressable (>= 2.3.5)
+ faraday (>= 0.17.3, < 3)
+ securerandom (0.4.1)
+ selenium-webdriver (4.32.0)
+ base64 (~> 0.2)
+ logger (~> 1.4)
+ rexml (~> 3.2, >= 3.2.5)
+ rubyzip (>= 1.2.2, < 3.0)
+ websocket (~> 1.0)
+ shellany (0.0.1)
+ shoulda (4.0.0)
+ shoulda-context (~> 2.0)
+ shoulda-matchers (~> 4.0)
+ shoulda-context (2.0.0)
+ shoulda-matchers (4.5.1)
+ activesupport (>= 4.2.0)
+ simpleidn (0.2.3)
+ singleton (0.3.0)
+ snaky_hash (2.0.3)
+ hashie (>= 0.1.0, < 6)
+ version_gem (>= 1.1.8, < 3)
+ spring (4.4.0)
+ spring-commands-rspec (1.0.4)
+ spring (>= 0.9.1)
+ spring-watcher-listen (2.1.0)
+ listen (>= 2.7, < 4.0)
+ spring (>= 4)
+ sprockets (4.2.2)
+ concurrent-ruby (~> 1.0)
+ logger
+ rack (>= 2.2.4, < 4)
+ sprockets-rails (3.5.2)
+ actionpack (>= 6.1)
+ activesupport (>= 6.1)
+ sprockets (>= 3.0.0)
+ stringio (3.1.7)
+ terminal-table (4.0.0)
+ unicode-display_width (>= 1.1.1, < 4)
+ text (1.3.1)
+ thor (1.4.0)
+ timeout (0.4.3)
+ tomparse (0.4.2)
+ translation (1.41)
+ gettext (~> 3.2, >= 3.2.5, <= 3.4.9)
+ tsort (0.2.0)
+ turbo-rails (2.0.17)
+ actionpack (>= 7.1.0)
+ railties (>= 7.1.0)
+ tzinfo (2.0.6)
+ concurrent-ruby (~> 1.0)
+ unicode-display_width (3.2.0)
+ unicode-emoji (~> 4.1)
+ unicode-emoji (4.1.0)
+ uniform_notifier (1.18.0)
+ uri (1.0.4)
+ version_gem (1.1.9)
+ warden (1.2.9)
+ rack (>= 2.0.9)
+ web-console (4.2.1)
+ actionview (>= 6.0.0)
+ activemodel (>= 6.0.0)
+ bindex (>= 0.4.0)
+ railties (>= 6.0.0)
+ webmock (3.25.1)
+ addressable (>= 2.8.0)
+ crack (>= 0.3.2)
+ hashdiff (>= 0.4.0, < 2.0.0)
+ websocket (1.2.11)
+ websocket-driver (0.8.0)
+ base64
+ websocket-extensions (>= 0.1.0)
+ websocket-extensions (0.1.5)
+ wicked_pdf (2.8.2)
+ activesupport
+ ostruct
+ wkhtmltopdf-binary (0.12.6.10)
+ xpath (3.2.0)
+ nokogiri (~> 1.8)
+ yard (0.9.37)
+ yard-tomdoc (0.7.1)
+ tomparse (>= 0.4.0)
+ yard
+ zeitwerk (2.6.18)
+
+PLATFORMS
+ aarch64-linux
+ arm64-darwin-21
+ arm64-darwin-22
+ x86_64-linux
+
+DEPENDENCIES
+ activerecord_json_validator
+ annotate
+ annotate_gem
+ api-pagination
+ autoprefixer-rails
+ better_errors
+ binding_of_caller
+ bootsnap
+ brakeman
+ bullet
+ bundle-audit
+ byebug
+ capybara
+ contact_us
+ cssbundling-rails
+ danger
+ database_cleaner
+ devise
+ devise_invitable
+ doorkeeper
+ dotenv-rails
+ dragonfly
+ dragonfly-s3_data_store
+ factory_bot_rails
+ faker
+ flag_shih_tzu
+ fuubar
+ guard
+ htmltoword
+ httparty
+ jbuilder
+ jsbundling-rails
+ jwt
+ kaminari
+ ledermann-rails-settings
+ listen
+ mail (= 2.7.1)
+ mimemagic
+ mocha
+ mysql2
+ net-smtp
+ omniauth
+ omniauth-orcid
+ omniauth-rails_csrf_protection
+ omniauth-shibboleth
+ parallel
+ pg
+ progress_bar
+ puma
+ pundit
+ pundit-matchers
+ rack-attack (~> 6.6, >= 6.6.1)
+ rack-mini-profiler
+ rails (~> 7.1)
+ rails-controller-testing
+ recaptcha
+ rollbar
+ rspec-collection_matchers
+ rspec-rails
+ rubocop
+ rubocop-i18n
+ rubocop-performance
+ ruby-progressbar
+ selenium-webdriver
+ shoulda
+ spring
+ spring-commands-rspec
+ spring-watcher-listen
+ sprockets-rails
+ text
+ translation
+ turbo-rails
+ web-console
+ webmock
+ wicked_pdf
+ wkhtmltopdf-binary
+ yard
+ yard-tomdoc
+
+RUBY VERSION
+ ruby 3.1.4p223
+
+BUNDLED WITH
+ 2.4.17
diff --git a/app/controllers/api/v2/base_api_controller.rb b/app/controllers/api/v2/base_api_controller.rb
new file mode 100644
index 0000000000..fa9e0143e0
--- /dev/null
+++ b/app/controllers/api/v2/base_api_controller.rb
@@ -0,0 +1,97 @@
+# frozen_string_literal: true
+
+module Api
+ module V2
+ class BaseApiController < ApplicationController # rubocop:todo Style/Documentation
+ # skipping the standard rails authenticity tokens passed in the UI
+ skip_before_action :verify_authenticity_token
+
+ # call doorkeeper to authorize the request
+ before_action :doorkeeper_authorize!, except: %i[heartbeat]
+ # get details of server (e.g. DMPonline) and client app
+ before_action :base_response_content
+
+ before_action :log_access
+
+ # controller can respond to json format requests
+ respond_to :json
+
+ # set up pages in response
+ before_action :pagination_params, except: %i[heartbeat]
+
+ rescue_from Exception, with: :handle_exception
+
+ # GET /api/v2/heartbeat
+ def heartbeat
+ render '/api/v2/heartbeat'
+ end
+
+ # GET /me.json - recommended for doorkeeper gem
+ def me
+ respond_with @resource_owner
+ end
+
+ private
+
+ # define instance variable json and associated getter and setter methods
+ attr_accessor :json
+
+ def base_response_content
+ @application = ApplicationService.application_name
+ @client = doorkeeper_token&.application
+ @caller = @client&.name || request.remote_ip
+ @scopes = doorkeeper_token.scopes.to_a if doorkeeper_token
+ return unless doorkeeper_token&.resource_owner_id
+
+ @resource_owner = User.find(doorkeeper_token.resource_owner_id)
+ end
+
+ def log_access
+ if @client.present?
+ Rails.logger.info "Client (OAuth) application name: #{@client.name}"
+ Rails.logger.info "Client (OAuth) application uid: #{@client.uid}"
+ end
+ Rails.logger.info "Resource owner id: #{@resource_owner.id}" if @resource_owner
+ end
+
+ def handle_exception(exception)
+ if exception.is_a?(Pundit::NotAuthorizedError)
+ handle_client_not_authorized
+ else
+ handle_internal_server_error(exception)
+ end
+ end
+
+ def handle_internal_server_error(exception)
+ # log server errors
+ Rails.logger.error "Exception message: #{exception.message}"
+
+ # inform client of server error
+ message = _('There was a problem in the server.')
+ @payload = { message: [message] }
+ render '/api/v2/error', status: :internal_server_error
+ end
+
+ def handle_client_not_authorized
+ message = _('The client is not authorized to perform this action.')
+ @payload = { message: [message] }
+ render '/api/v2/error', status: :forbidden
+ end
+
+ # retrieve the requested pagination params or use defaults
+ # only allow 100 per page as the max
+ def pagination_params
+ max_per_page = Rails.configuration.x.application.api_max_page_size
+ @page = params.fetch('page', 1).to_i
+ @per_page = params.fetch('per_page', max_per_page).to_i
+ @per_page = max_per_page if @per_page > max_per_page
+ end
+
+ def paginate_response(results:)
+ results = results.page(@page).per(@per_page)
+ @total_items = results.total_count
+ results
+ end
+ end
+ end
+end
diff --git a/app/controllers/api/v2/plans_controller.rb b/app/controllers/api/v2/plans_controller.rb
new file mode 100644
index 0000000000..7714e9c892
--- /dev/null
+++ b/app/controllers/api/v2/plans_controller.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+module Api
+ module V2
+ class PlansController < BaseApiController # rubocop:todo Style/Documentation
+ respond_to :json
+
+ # GET /api/v2/plans/:id
+ def show
+ raise Pundit::NotAuthorizedError unless @scopes.include?('read')
+
+ @plan = Plan.find_by(id: params[:id])
+
+ raise Pundit::NotAuthorizedError unless @plan.present?
+
+ plans_policy = PlansPolicy.new(@resource_owner, @plan)
+ raise Pundit::NotAuthorizedError unless plans_policy.show?
+
+ @items = [@plan]
+ render '/api/v2/plans/index', status: :ok
+ end
+
+ # GET /api/v2/plans
+ def index
+ raise Pundit::NotAuthorizedError unless @scopes.include?('read')
+
+ @plans = PlansPolicy::Scope.new(@resource_owner).resolve
+ @items = paginate_response(results: @plans)
+ render '/api/v2/plans/index', status: :ok
+ end
+ end
+ end
+end
diff --git a/app/controllers/api/v2/templates_controller.rb b/app/controllers/api/v2/templates_controller.rb
new file mode 100644
index 0000000000..5e732506dc
--- /dev/null
+++ b/app/controllers/api/v2/templates_controller.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Api
+ module V2
+ # provides a list of templates for API V2
+ class TemplatesController < BaseApiController
+ respond_to :json
+
+ # GET /api/v2/templates
+ def index
+ raise Pundit::NotAuthorizedError unless @scopes.include?('read')
+
+ templates = Api::V2::TemplatesPolicy::Scope.new(@resource_owner).resolve
+ @items = paginate_response(results: templates)
+ render '/api/v2/templates/index', status: :ok
+ end
+ end
+ end
+end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 1e2c29fcce..e5d2421e76 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -66,6 +66,9 @@ def store_location
# rubocop:disable Metrics/AbcSize
def after_sign_in_path_for(_resource)
+ # ensure oauth2 authorization flow is not interrupted
+ return session[:user_return_to] if user_is_in_oauth_flow
+
referer_path = URI(request.referer).path unless request.referer.nil?
if from_external_domain? || referer_path.eql?(new_user_session_path) ||
referer_path.eql?(new_user_registration_path) ||
@@ -77,7 +80,10 @@ def after_sign_in_path_for(_resource)
end
# rubocop:enable Metrics/AbcSize
- def after_sign_up_path_for(_resource)
+ def after_sign_up_path_for(_resource) # rubocop:todo Metrics/AbcSize
+ # ensure oauth2 authorization flow is not interrupted
+ return session[:user_return_to] if user_is_in_oauth_flow
+
referer_path = URI(request.referer).path unless request.referer.nil?
if from_external_domain? ||
referer_path.eql?(new_user_session_path) ||
@@ -197,4 +203,8 @@ def render_respond_to_format_with_error_message(msg, url_or_path, http_status, e
end
end
end
+
+ def user_is_in_oauth_flow
+ session[:user_return_to].present? && session[:user_return_to].include?('/oauth/authorize')
+ end
end
diff --git a/app/controllers/concerns/plan_permitted_params.rb b/app/controllers/concerns/plan_permitted_params.rb
new file mode 100644
index 0000000000..90363f9de8
--- /dev/null
+++ b/app/controllers/concerns/plan_permitted_params.rb
@@ -0,0 +1,158 @@
+# frozen_string_literal: true
+
+module PlanPermittedParams # rubocop:todo Metrics/ModuleLength, Style/Documentation
+ extend ActiveSupport::Concern
+
+ def plan_permitted_params
+ [
+ :created,
+ :title,
+ :description,
+ :language,
+ :ethical_issues_exist,
+ :ethical_issues_description,
+ :ethical_issues_report,
+ { dmp_ids: identifier_permitted_params },
+ { contact: contributor_permitted_params },
+ { contributors: contributor_permitted_params },
+ { costs: cost_permitted_params },
+ { project: project_permitted_params },
+ { datasets: dataset_permitted_params }
+ ]
+ end
+
+ def identifier_permitted_params
+ %i[
+ type
+ identifier
+ ]
+ end
+
+ def contributor_permitted_params
+ [
+ :firstname,
+ :surname,
+ :mbox,
+ :role,
+ { affiliations: affiliation_permitted_params },
+ { contributor_ids: identifier_permitted_params }
+ ]
+ end
+
+ def affiliation_permitted_params
+ [
+ :name,
+ :abbreviation,
+ { affiliation_ids: identifier_permitted_params }
+ ]
+ end
+
+ def cost_permitted_params
+ %i[
+ title
+ description
+ value
+ currency_code
+ ]
+ end
+
+ def project_permitted_params
+ [
+ :title,
+ :description,
+ :start_on,
+ :end_on,
+ { funding: funding_permitted_params }
+ ]
+ end
+
+ def funding_permitted_params
+ [
+ :name,
+ :funding_status,
+ { funder_ids: identifier_permitted_params },
+ { grant_ids: identifier_permitted_params }
+ ]
+ end
+
+ def dataset_permitted_params
+ [
+ :title,
+ :doi_url,
+ :description,
+ :type,
+ :issued,
+ :language,
+ :personal_data,
+ :sensitive_data,
+ :keywords,
+ :data_quality_assurance,
+ :preservation_statement,
+ { dataset_ids: identifier_permitted_params },
+ { metadata: metadatum_permitted_params },
+ { security_and_privacy_statements: security_and_privacy_statement_permitted_params },
+ { technical_resources: technical_resource_permitted_params },
+ { distributions: distribution_permitted_params }
+ ]
+ end
+
+ def metadatum_permitted_params
+ [
+ :description,
+ :language,
+ { identifier: identifier_permitted_params }
+ ]
+ end
+
+ def security_and_privacy_statement_permitted_params
+ %i[
+ title
+ description
+ ]
+ end
+
+ def technical_resource_permitted_params
+ [
+ :description,
+ { identifier: identifier_permitted_params }
+ ]
+ end
+
+ def distribution_permitted_params
+ [
+ :title,
+ :description,
+ :format,
+ :byte_size,
+ :access_url,
+ :download_url,
+ :data_access,
+ :available_until,
+ { licenses: license_permitted_params },
+ { host: host_permitted_params }
+ ]
+ end
+
+ def license_permitted_params
+ %i[
+ license_ref
+ start_date
+ ]
+ end
+
+ def host_permitted_params
+ [
+ :title,
+ :description,
+ :supports_versioning,
+ :backup_type,
+ :backup_frequency,
+ :storage_type,
+ :availability,
+ :geo_location,
+ :certified_with,
+ :pid_system,
+ { host_ids: identifier_permitted_params }
+ ]
+ end
+end
diff --git a/app/models/oauth_access_grant.rb b/app/models/oauth_access_grant.rb
new file mode 100644
index 0000000000..f39c307af9
--- /dev/null
+++ b/app/models/oauth_access_grant.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+# == Schema Information
+#
+# Table name: oauth_access_grants
+#
+# id: :integer
+# resource_owner_id: :integer
+# application_id: :integer
+# token: :string
+# expires_in: :integer
+# redirect_uri: :text
+# scopes: :string
+# created_at: :datetime
+# revoked_at: :datetime
+
+class OauthAccessGrant < ApplicationRecord
+end
diff --git a/app/models/oauth_access_token.rb b/app/models/oauth_access_token.rb
new file mode 100644
index 0000000000..b17e824e72
--- /dev/null
+++ b/app/models/oauth_access_token.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+# == Schema Information
+#
+# Table name: oauth_access_tokens
+#
+# id: :integer
+# resource_owner_id: :integer
+# application_id: :integer
+# token: :string
+# refresh_token: :string
+# expires_in: :integer
+# scopes: :string
+# created_at: :datetime
+# revoked_at: :datetime
+# previous_refresh_token: :string
+
+class OauthAccessToken < ApplicationRecord
+end
diff --git a/app/models/oauth_application.rb b/app/models/oauth_application.rb
new file mode 100644
index 0000000000..4779e53cc4
--- /dev/null
+++ b/app/models/oauth_application.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+# == Schema Information
+#
+# Table name: oauth_applications
+#
+# id: :integer
+# name: :string
+# uid: :string
+# secret: :string
+# redirect_uri: :text
+# scopes: :string
+# confidential: :boolean
+# created_at: :datetime
+# updated_at: :datetime
+
+class OauthApplication < ApplicationRecord
+end
diff --git a/app/models/user.rb b/app/models/user.rb
index 94d0035eec..8732c2f770 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -98,6 +98,12 @@ class User < ApplicationRecord
has_and_belongs_to_many :notifications, dependent: :destroy,
join_table: 'notification_acknowledgements'
+ has_many :access_grants, class_name: 'Doorkeeper::AccessGrant', foreign_key: :resource_owner_id,
+ dependent: :delete_all
+
+ has_many :access_tokens, class_name: 'Doorkeeper::AccessToken', foreign_key: :resource_owner_id,
+ dependent: :delete_all
+
# ===============
# = Validations =
# ===============
diff --git a/app/policies/api/v2/plans_policy.rb b/app/policies/api/v2/plans_policy.rb
new file mode 100644
index 0000000000..98a22a5025
--- /dev/null
+++ b/app/policies/api/v2/plans_policy.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Api
+ module V2
+ # Security rules for API V2 Plan endpoints
+ class PlansPolicy < ApplicationPolicy
+ # overriding the initializer due to resource owner / user
+ # not needing to be logged in for client app to make requests
+ def initialize(resource_owner, plan = nil) # rubocop:todo Lint/MissingSuper
+ @resource_owner = resource_owner
+ @plan = plan
+ end
+
+ def show?
+ @plan.roles.where(user_id: @resource_owner.id, active: true).exists?
+ end
+
+ class Scope < Scope # rubocop:todo Style/Documentation
+ def initialize(resource_owner) # rubocop:todo Lint/MissingSuper
+ @resource_owner = resource_owner
+ end
+
+ def resolve
+ Plan.joins(:roles)
+ .where(roles: { user_id: @resource_owner.id, active: true })
+ .distinct
+ end
+ end
+ end
+ end
+end
diff --git a/app/policies/api/v2/templates_policy.rb b/app/policies/api/v2/templates_policy.rb
new file mode 100644
index 0000000000..dacdfe48a2
--- /dev/null
+++ b/app/policies/api/v2/templates_policy.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Api
+ module V2
+ class TemplatesPolicy < ApplicationPolicy
+ class Scope < Scope # rubocop:todo Style/Documentation
+ def initialize(resource_owner) # rubocop:todo Lint/MissingSuper
+ @resource_owner = resource_owner
+ end
+
+ def resolve
+ # create the sql where clause
+ where_clause = <<-SQL
+ (visibility = 0 AND org_id = ?) OR
+ (visibility = 1 AND customization_of IS NULL)
+ SQL
+
+ # get the templates
+ Template
+ .includes(org: :identifiers)
+ .joins(:org)
+ .published
+ .where(
+ where_clause,
+ @resource_owner.org&.id
+ )
+ .order(:title)
+ end
+ end
+ end
+ end
+end
diff --git a/app/presenters/api/v2/api_presenter.rb b/app/presenters/api/v2/api_presenter.rb
new file mode 100644
index 0000000000..1ad7290ab6
--- /dev/null
+++ b/app/presenters/api/v2/api_presenter.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Api
+ module V2
+ # Generic helper methods for API V2
+ class ApiPresenter
+ class << self
+ def boolean_to_yes_no_unknown(value:)
+ return 'unknown' unless value.present?
+
+ value ? 'yes' : 'no'
+ end
+ end
+ end
+ end
+end
diff --git a/app/presenters/api/v2/contributor_presenter.rb b/app/presenters/api/v2/contributor_presenter.rb
new file mode 100644
index 0000000000..77232c2838
--- /dev/null
+++ b/app/presenters/api/v2/contributor_presenter.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Api
+ module V2
+ # Helper class for the API V2 contributors views
+ class ContributorPresenter
+ class << self
+ # Convert the specified role into a CRediT Taxonomy URL
+ def role_as_uri(role:)
+ return nil unless role.present?
+ return 'other' if role.to_s.casecmp('other').zero?
+
+ "#{Contributor::ONTOLOGY_BASE_URL}/#{role.to_s.downcase.tr('_', '-')}"
+ end
+
+ def contributor_id(identifiers:)
+ identifiers.find { |id| id.identifier_scheme.name == 'orcid' }
+ end
+ end
+ end
+ end
+end
diff --git a/app/presenters/api/v2/funding_presenter.rb b/app/presenters/api/v2/funding_presenter.rb
new file mode 100644
index 0000000000..c878daadb6
--- /dev/null
+++ b/app/presenters/api/v2/funding_presenter.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Api
+ module V2
+ # Helper class for the API V2 funding section
+ class FundingPresenter
+ class << self
+ # If the plan has a grant number then it has been awarded/granted
+ # otherwise it is 'planned'
+ def status(plan:)
+ return 'planned' unless plan.present?
+
+ case plan.funding_status
+ when 'funded'
+ 'granted'
+ when 'denied'
+ 'rejected'
+ else
+ 'planned'
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/app/presenters/api/v2/language_presenter.rb b/app/presenters/api/v2/language_presenter.rb
new file mode 100644
index 0000000000..1b9d8aebce
--- /dev/null
+++ b/app/presenters/api/v2/language_presenter.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+module Api
+ module V2
+ # Helper class for the API V2 language values
+ class LanguagePresenter
+ class << self
+ LANGUAGE_MAP = {
+ aa: 'aar', ab: 'abk', af: 'afr', ak: 'aka', am: 'amh', ar: 'ara', an: 'arg',
+ as: 'asm', av: 'ava', ae: 'ave', ay: 'aym', az: 'aze',
+
+ ba: 'bak', bm: 'bam', be: 'bel', bn: 'ben', bh: 'bih', bi: 'bis', bo: 'tib',
+ bs: 'bos', br: 'bre', bg: 'bul',
+
+ ca: 'cat', cs: 'cze', ch: 'cha', ce: 'che', cu: 'chu', cv: 'chv', co: 'cos',
+ cr: 'cre', cy: 'wel',
+
+ da: 'dan', de: 'deu', dv: 'div', dz: 'dzo',
+
+ el: 'gre', en: 'eng', eo: 'epo', es: 'spa', et: 'est', eu: 'baq', ee: 'ewe',
+
+ fo: 'fao', fa: 'per', fj: 'fij', fi: 'fin', fr: 'fre', fy: 'fry', ff: 'ful',
+
+ gd: 'gla', ga: 'gle', gl: 'glg', gv: 'glv', gn: 'grn', gu: 'guj',
+
+ ht: 'hat', ha: 'hau', he: 'heb', hz: 'her', hi: 'hin', ho: 'hmo', hr: 'hrv',
+ hu: 'hun', hy: 'arm',
+
+ ig: 'ibo', io: 'ido', ii: 'iii', iu: 'iku', ie: 'ile', ia: 'ina', id: 'ind',
+ ik: 'ipk', is: 'ice', it: 'ita',
+
+ jv: 'jav', ja: 'jpn',
+
+ kl: 'kal', kn: 'kan', ks: 'kas', kr: 'kau', kk: 'kaz', km: 'khm', ki: 'kik',
+ ky: 'kir', kv: 'kom', kg: 'kon', ko: 'kor', kj: 'kua', ku: 'kur', ka: 'geo',
+ kw: 'cor',
+
+ lo: 'lao', la: 'lat', lv: 'lav', li: 'lim', ln: 'lin', lt: 'lit', lb: 'ltz',
+ lu: 'lub', lg: 'lug',
+
+ mk: 'mac', mh: 'mah', ml: 'mal', mi: 'mao', mr: 'mar', ms: 'may', mg: 'mlg',
+ mt: 'mlt', mn: 'mon', my: 'bur',
+
+ na: 'nau', nv: 'nav', nr: 'nbl', nd: 'nde', ng: 'ndo', ne: 'nep', nl: 'dut',
+ nn: 'nno', nb: 'nob', no: 'nor', ny: 'nya',
+
+ oc: 'oci', oj: 'oji', or: 'ori', om: 'orm', os: 'oss',
+
+ pa: 'pan', pi: 'pli', pl: 'pol', pt: 'por', ps: 'pus',
+
+ qu: 'que',
+
+ rm: 'roh', ro: 'rum', rn: 'run', ru: 'rus', rw: 'kin',
+
+ sg: 'sag', sa: 'san', si: 'sin', sk: 'slo', sl: 'slv', se: 'sme', sm: 'smo',
+ sn: 'sna', sd: 'snd', so: 'som', st: 'sot', sq: 'alb', sc: 'srd', sr: 'srp',
+ ss: 'ssw', su: 'sun', sw: 'swa', sv: 'swe',
+
+ ty: 'tah', ta: 'tam', tt: 'tat', te: 'tel', tg: 'tgk', tl: 'tgl', th: 'tha',
+ ti: 'tir', to: 'ton', tn: 'tsn', ts: 'tso', tk: 'tuk', tr: 'tur', tw: 'twi',
+
+ ug: 'uig', uk: 'ukr', ur: 'urd', uz: 'uzb',
+
+ ve: 'ven', vi: 'vie', vo: 'vol',
+
+ wa: 'wln', wo: 'wol',
+
+ xh: 'xho',
+
+ yi: 'yid', yo: 'yor',
+
+ za: 'zha', zh: 'chi', zu: 'zul'
+ }.freeze
+
+ # Convert the incoming 2 (e.g. en - ISO 639-1) or 2+region (e.g. en-UK)
+ # into the 3 character code (e.g. eng - ISO 639-2)
+ def three_char_code(lang:)
+ two_char_code = lang.to_s.split('-').first
+ LANGUAGE_MAP[two_char_code.to_sym]
+ end
+ end
+ end
+ end
+end
diff --git a/app/presenters/api/v2/org_presenter.rb b/app/presenters/api/v2/org_presenter.rb
new file mode 100644
index 0000000000..5302acb7a7
--- /dev/null
+++ b/app/presenters/api/v2/org_presenter.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Api
+ module V2
+ # Helper class for the API V2 affiliation sections
+ class OrgPresenter
+ class << self
+ def affiliation_id(identifiers:)
+ ident = identifiers.find { |id| id.identifier_scheme&.name == 'ror' }
+ return ident if ident.present?
+
+ identifiers.find { |id| id.identifier_scheme&.name == 'fundref' }
+ end
+ end
+ end
+ end
+end
diff --git a/app/presenters/api/v2/pagination_presenter.rb b/app/presenters/api/v2/pagination_presenter.rb
new file mode 100644
index 0000000000..1b8fbc1109
--- /dev/null
+++ b/app/presenters/api/v2/pagination_presenter.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module Api
+ module V2
+ # Helper class for genewric API V2 pagination
+ class PaginationPresenter
+ def initialize(current_url:, per_page:, total_items:, current_page: 1)
+ @url = current_url
+ @per_page = per_page
+ @total_items = total_items
+ @page = current_page
+ end
+
+ def url_without_pagination
+ return nil unless @url.present? && @url.is_a?(String)
+
+ url = @url.gsub(/per_page=\d+/, '')
+ .gsub(/page=\d+/, '')
+ .gsub(/(&)+$/, '').gsub(/\?$/, '')
+
+ (url.include?('?') ? "#{url}&" : "#{url}?")
+ end
+
+ def prev_page?
+ total_pages > 1 && @page != 1
+ end
+
+ def next_page?
+ total_pages > 1 && @page < total_pages
+ end
+
+ def prev_page_link
+ "#{url_without_pagination}page=#{@page - 1}&per_page=#{@per_page}"
+ end
+
+ def next_page_link
+ "#{url_without_pagination}page=#{@page + 1}&per_page=#{@per_page}"
+ end
+
+ private
+
+ def total_pages
+ return 1 unless @total_items.present? && @per_page.present? &&
+ @total_items.positive? && @per_page.positive?
+
+ (@total_items.to_f / @per_page).ceil
+ end
+ end
+ end
+end
diff --git a/app/presenters/api/v2/plan_presenter.rb b/app/presenters/api/v2/plan_presenter.rb
new file mode 100644
index 0000000000..204cd68011
--- /dev/null
+++ b/app/presenters/api/v2/plan_presenter.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+module Api
+ module V2
+ # Helper class for the API V2 project / DMP
+ class PlanPresenter
+ attr_reader :data_contact, :contributors, :costs
+
+ def initialize(plan:)
+ @contributors = []
+ return unless plan.present?
+
+ @plan = plan
+
+ @data_contact = @plan.owner
+
+ # Attach the first data_curation role as the data_contact, otherwise
+ # add the contributor to the contributors array
+ @plan.contributors.each do |contributor|
+ @data_contact = contributor if contributor.data_curation? && @data_contact.nil?
+ @contributors << contributor
+ end
+
+ @costs = plan_costs(plan: @plan)
+ end
+
+ # Extract the ARK or DOI for the DMP OR use its URL if none exists
+ def identifier
+ doi = @plan.identifiers.select do |id|
+ ::Plan::DMP_ID_TYPES.include?(id.identifier_format)
+ end
+ return doi.first if doi.first.present?
+
+ # if no DOI then use the URL for the API's 'show' method
+ Identifier.new(value: Rails.application.routes.url_helpers.api_v2_plan_url(@plan))
+ end
+
+ private
+
+ # Retrieve the answers that have the Budget theme
+ def plan_costs(plan:)
+ theme = Theme.where(title: 'Cost').first
+ return [] unless theme.present?
+
+ # TODO: define a new 'Currency' question type that includes a float field
+ # any currency type selector (e.g GBP or USD)
+ answers = plan.answers.includes(question: :themes).select do |answer|
+ answer.question.themes.include?(theme)
+ end
+
+ answers.map do |answer|
+ # TODO: Investigate whether question level guidance should be the description
+ { title: answer.question.text, description: nil,
+ currency_code: 'usd', value: answer.text }
+ end
+ end
+ end
+ end
+end
diff --git a/app/presenters/api/v2/research_output_presenter.rb b/app/presenters/api/v2/research_output_presenter.rb
new file mode 100644
index 0000000000..fc44055b2d
--- /dev/null
+++ b/app/presenters/api/v2/research_output_presenter.rb
@@ -0,0 +1,77 @@
+# frozen_string_literal: true
+
+module Api
+ module V2
+ # Helper methods for research outputs
+ class ResearchOutputPresenter
+ attr_reader :dataset_id, :preservation_statement, :security_and_privacy, :license_start_date,
+ :data_quality_assurance, :distributions, :metadata, :technical_resources
+
+ def initialize(output:)
+ @research_output = output
+ return unless output.is_a?(ResearchOutput)
+
+ @plan = output.plan
+ @dataset_id = identifier
+
+ load_narrative_content
+
+ @license_start_date = determine_license_start_date(output: output)
+ end
+
+ private
+
+ def identifier
+ Identifier.new(identifiable: @research_output, value: @research_output.id)
+ end
+
+ def determine_license_start_date(output:)
+ return nil unless output.present?
+ return output.release_date.to_formatted_s(:iso8601) if output.release_date.present?
+
+ output.created_at.to_formatted_s(:iso8601)
+ end
+
+ def load_narrative_content
+ @preservation_statement = ''
+ @security_and_privacy = []
+ @data_quality_assurance = ''
+
+ # Disabling rubocop here since a guard clause would make the line too long
+ # rubocop:disable Style/GuardClause
+ if Rails.configuration.x.madmp.extract_preservation_statements_from_themed_questions
+ @preservation_statement = fetch_q_and_a_as_single_statement(themes: %w[Preservation])
+ end
+ if Rails.configuration.x.madmp.extract_security_privacy_statements_from_themed_questions
+ @security_and_privacy = fetch_q_and_a(themes: ['Ethics & privacy', 'Storage & security'])
+ end
+ if Rails.configuration.x.madmp.extract_data_quality_statements_from_themed_questions
+ @data_quality_assurance = fetch_q_and_a_as_single_statement(themes: ['Data Collection'])
+ end
+ # rubocop:enable Style/GuardClause
+ end
+
+ def fetch_q_and_a_as_single_statement(themes:)
+ fetch_q_and_a(themes: themes).collect { |item| item[:description] }.join('
')
+ end
+
+ # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
+ def fetch_q_and_a(themes:)
+ return [] unless themes.is_a?(Array) && themes.any?
+
+ ret = themes.map do |theme|
+ qs = @plan.questions.select { |q| q.themes.collect(&:title).include?(theme) }
+ descr = qs.map do |q|
+ a = @plan.answers.find { |ans| ans.question_id = q.id }
+ next unless a.present? && !a.blank?
+
+ "Question: #{q.text}
Answer: #{a.text}"
+ end
+ { title: theme, description: descr }
+ end
+ ret.select { |item| item[:description].present? }
+ end
+ # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
+ end
+ end
+end
diff --git a/app/presenters/api/v2/template_presenter.rb b/app/presenters/api/v2/template_presenter.rb
new file mode 100644
index 0000000000..2d32a45d37
--- /dev/null
+++ b/app/presenters/api/v2/template_presenter.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Api
+ module V2
+ # Helper class for the API V2 template info
+ class TemplatePresenter
+ def initialize(template:)
+ @template = template
+ end
+
+ # If the plan has a grant number then it has been awarded/granted
+ # otherwise it is 'planned'
+ def title
+ return @template.title unless @template.customization_of.present?
+
+ "#{@template.title} - with additional questions for #{@template.org.name}"
+ end
+ end
+ end
+end
diff --git a/app/services/api/v2/conversion_service.rb b/app/services/api/v2/conversion_service.rb
new file mode 100644
index 0000000000..4a9a932878
--- /dev/null
+++ b/app/services/api/v2/conversion_service.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Api
+ module V2
+ # Helper service that translates to/from the RDA common standard
+ class ConversionService
+ class << self
+ # Converts a boolean field to [yes, no, unknown]
+ def boolean_to_yes_no_unknown(value)
+ return 'yes' if [true, 1].include?(value)
+
+ return 'no' if [false, 0].include?(value)
+
+ 'unknown'
+ end
+
+ # Converts a [yes, no, unknown] field to boolean (or nil)
+ def yes_no_unknown_to_boolean(value)
+ return true if value&.downcase == 'yes'
+
+ return nil if value.blank? || value&.downcase == 'unknown'
+
+ false
+ end
+
+ # Converts the context and value into an Identifier with a psuedo
+ # IdentifierScheme for display in JSON partials. Which will result in:
+ # { type: 'context', identifier: 'value' }
+ def to_identifier(context:, value:)
+ return nil unless value.present? && context.present?
+
+ scheme = IdentifierScheme.new(name: context)
+ Identifier.new(value: value, identifier_scheme: scheme)
+ end
+ end
+ end
+ end
+end
diff --git a/app/views/api/v2/_standard_response.json.jbuilder b/app/views/api/v2/_standard_response.json.jbuilder
new file mode 100644
index 0000000000..372c42cb31
--- /dev/null
+++ b/app/views/api/v2/_standard_response.json.jbuilder
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+# locals: response, request, total_items
+
+total_items ||= 0
+
+paginator = Api::V2::PaginationPresenter.new(current_url: request.path,
+ per_page: @per_page,
+ total_items: total_items,
+ current_page: @page)
+
+json.prettify!
+json.ignore_nil!
+
+json.application @application
+json.source "#{request.method} #{request.path}"
+json.time Time.now.to_formatted_s(:iso8601)
+json.caller @caller
+json.code response.status
+json.message Rack::Utils::HTTP_STATUS_CODES[response.status]
+
+if response.status == 200
+
+ # Pagination Links
+ if total_items.positive?
+ json.page @page
+ json.per_page @per_page
+ json.total_items total_items
+
+ # Prepare the base URL by removing the old pagination params
+ json.prev paginator.prev_page_link if paginator.prev_page?
+ json.next paginator.next_page_link if paginator.next_page?
+ else
+ json.total_items 0
+ end
+
+end
diff --git a/app/views/api/v2/contributors/_show.json.jbuilder b/app/views/api/v2/contributors/_show.json.jbuilder
new file mode 100644
index 0000000000..267ff7e3d2
--- /dev/null
+++ b/app/views/api/v2/contributors/_show.json.jbuilder
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+# locals: contributor, is_contact
+
+is_contact ||= false
+
+json.name contributor.is_a?(User) ? contributor.name(false) : contributor.name
+json.mbox contributor.email
+
+if !is_contact && contributor.selected_roles.any?
+ roles = contributor.selected_roles.map do |role|
+ Api::V2::ContributorPresenter.role_as_uri(role: role)
+ end
+ json.role roles if roles.any?
+end
+
+if contributor.org.present?
+ json.affiliation do
+ json.partial! 'api/v2/orgs/show', org: contributor.org
+ end
+end
+
+orcid = contributor.identifier_for_scheme(scheme: 'orcid')
+if orcid.present?
+ id = Api::V2::ContributorPresenter.contributor_id(
+ identifiers: contributor.identifiers
+ )
+ if is_contact
+ json.contact_id do
+ json.partial! 'api/v2/identifiers/show', identifier: id
+ end
+ else
+ json.contributor_id do
+ json.partial! 'api/v2/identifiers/show', identifier: id
+ end
+ end
+end
diff --git a/app/views/api/v2/datasets/_show.json.jbuilder b/app/views/api/v2/datasets/_show.json.jbuilder
new file mode 100644
index 0000000000..6e856019cd
--- /dev/null
+++ b/app/views/api/v2/datasets/_show.json.jbuilder
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+# locals: output
+
+if output.is_a?(ResearchOutput)
+ presenter = Api::V2::ResearchOutputPresenter.new(output: output)
+
+ json.type output.output_type
+ json.title output.title
+ json.description output.description
+ json.personal_data Api::V2::ApiPresenter.boolean_to_yes_no_unknown(value: output.personal_data)
+ json.sensitive_data Api::V2::ApiPresenter.boolean_to_yes_no_unknown(value: output.sensitive_data)
+ json.issued output.release_date&.to_formatted_s(:iso8601)
+
+ json.preservation_statement presenter.preservation_statement
+ json.security_and_privacy presenter.security_and_privacy
+ json.data_quality_assurance presenter.data_quality_assurance
+
+ json.dataset_id do
+ json.partial! "api/v2/identifiers/show", identifier: presenter.dataset_id
+ end
+
+ json.distribution output.repositories do |repository|
+ json.title "Anticipated distribution for #{output.title}"
+ json.byte_size output.byte_size
+ json.data_access output.access
+
+ json.host do
+ json.title repository.name
+ json.description repository.description
+ json.url repository.homepage
+
+ # DMPTool extensions to the RDA common metadata standard
+ json.dmproadmap_host_id do
+ json.type "url"
+ json.identifier repository.uri
+ end
+ end
+
+ if output.license.present?
+ json.license [output.license] do |license|
+ json.license_ref license.uri
+ json.start_date presenter.license_start_date
+ end
+ end
+ end
+
+ json.metadata output.metadata_standards do |metadata_standard|
+ website = metadata_standard.locations.find { |loc| loc["type"] == "website" }
+ website = { url: "" } unless website.present?
+
+ descr_array = [metadata_standard.title, metadata_standard.description, website["url"]]
+ json.description descr_array.join(" - ")
+
+ json.metadata_standard_id do
+ json.type "url"
+ json.identifier metadata_standard.uri
+ end
+ end
+
+ json.technical_resource []
+
+ if output.plan.research_domain_id.present?
+ research_domain = ResearchDomain.find_by(id: output.plan.research_domain_id)
+ if research_domain.present?
+ combined = "#{research_domain.identifier} - #{research_domain.label}"
+ json.keyword [research_domain.label, combined]
+ end
+ end
+
+else
+ json.type "dataset"
+ json.title "Generic dataset"
+ json.description "No individual datasets have been defined for this DMP."
+
+ if output.research_domain_id.present?
+ research_domain = ResearchDomain.find_by(id: output.research_domain_id)
+ if research_domain.present?
+ combined = "#{research_domain.identifier} - #{research_domain.label}"
+ json.keyword [research_domain.label, combined]
+ end
+ end
+end
diff --git a/app/views/api/v2/error.json.jbuilder b/app/views/api/v2/error.json.jbuilder
new file mode 100644
index 0000000000..ac08f26d9f
--- /dev/null
+++ b/app/views/api/v2/error.json.jbuilder
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+json.partial! 'api/v2/standard_response'
+
+# json.items []
+json.message @payload[:message]
+json.details @payload[:details]
diff --git a/app/views/api/v2/heartbeat.json.jbuilder b/app/views/api/v2/heartbeat.json.jbuilder
new file mode 100644
index 0000000000..70b165b95d
--- /dev/null
+++ b/app/views/api/v2/heartbeat.json.jbuilder
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+json.partial! 'api/v2/standard_response'
+
+json.items []
diff --git a/app/views/api/v2/identifiers/_show.json.jbuilder b/app/views/api/v2/identifiers/_show.json.jbuilder
new file mode 100644
index 0000000000..c219222aee
--- /dev/null
+++ b/app/views/api/v2/identifiers/_show.json.jbuilder
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+# locals: identifier
+
+json.type identifier&.identifier_format
+json.identifier identifier&.value
diff --git a/app/views/api/v2/me.json.jbuilder b/app/views/api/v2/me.json.jbuilder
new file mode 100644
index 0000000000..18a1e7c114
--- /dev/null
+++ b/app/views/api/v2/me.json.jbuilder
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+json.partial! 'api/v2/standard_response'
+
+if current_user.present?
+ json.items [current_user] do |user|
+ json.name [user.surname, user.firstname].join(', ')
+ json.mbox user.email
+ json.token user.ui_token
+
+ if user.org.present? && ['No funder', 'Non Partner Institution'].exclude?(user.org.name)
+ json.affiliation do
+ json.partial! 'api/v2/orgs/show', org: user.org
+ end
+ end
+
+ orcid = user.identifier_for_scheme(scheme: 'orcid')
+ if orcid.present?
+ json.user_id do
+ json.partial! 'api/v2/identifiers/show', identifier: orcid
+ end
+ end
+ end
+
+else
+ json.items []
+end
diff --git a/app/views/api/v2/orgs/_show.json.jbuilder b/app/views/api/v2/orgs/_show.json.jbuilder
new file mode 100644
index 0000000000..934e429a17
--- /dev/null
+++ b/app/views/api/v2/orgs/_show.json.jbuilder
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+# locals: org
+
+json.name org.name
+json.abbreviation org.abbreviation
+json.region org.region&.abbreviation
+
+if org.identifiers.any?
+ json.affiliation_id do
+ id = Api::V2::OrgPresenter.affiliation_id(identifiers: org.identifiers)
+ json.partial! 'api/v2/identifiers/show', identifier: id
+ end
+end
diff --git a/app/views/api/v2/plans/_cost.json.jbuilder b/app/views/api/v2/plans/_cost.json.jbuilder
new file mode 100644
index 0000000000..ad36e3540e
--- /dev/null
+++ b/app/views/api/v2/plans/_cost.json.jbuilder
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+# locals: cost
+
+json.title cost[:title]
+json.description cost[:description]
+json.currency_code cost[:currency_code]
+json.value cost[:value]
diff --git a/app/views/api/v2/plans/_funding.json.jbuilder b/app/views/api/v2/plans/_funding.json.jbuilder
new file mode 100644
index 0000000000..35786ac2dc
--- /dev/null
+++ b/app/views/api/v2/plans/_funding.json.jbuilder
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+# locals: plan
+
+json.name plan.funder&.name
+
+if plan.funder.present?
+ id = Api::V2::OrgPresenter.affiliation_id(identifiers: plan.funder.identifiers)
+
+ if id.present?
+ json.funder_id do
+ json.partial! 'api/v2/identifiers/show', identifier: id
+ end
+ end
+end
+
+if plan.grant_id.present? && plan.grant.present?
+ json.grant_id do
+ json.partial! 'api/v2/identifiers/show', identifier: plan.grant
+ end
+end
+
+json.funding_status Api::V2::FundingPresenter.status(plan: plan)
+
+# DMPTool extensions to the RDA common metadata standard
+# ------------------------------------------------------
+
+# We collect a user entered ID on the form, so this is a way to convey it to other systems
+# The ID would typically be something relevant to the funder or research organization
+if plan.identifier.present?
+ json.dmproadmap_funding_opportunity_id do
+ json.partial! 'api/v2/identifiers/show', identifier: Identifier.new(identifiable: plan,
+ value: plan.identifier)
+ end
+end
+
+# Since the Plan owner (aka contact) and contributor orgs could be different than the
+# one associated with the Plan, we add it here.
+json.dmproadmap_funded_affiliations [plan.org] do |funded_org|
+ json.partial! 'api/v2/orgs/show', org: funded_org
+end
diff --git a/app/views/api/v2/plans/_project.json.jbuilder b/app/views/api/v2/plans/_project.json.jbuilder
new file mode 100644
index 0000000000..9bf3f97fea
--- /dev/null
+++ b/app/views/api/v2/plans/_project.json.jbuilder
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+# locals: plan
+
+json.title plan.title
+json.description plan.description
+
+start_date = plan.start_date || Time.now
+json.start start_date.to_formatted_s(:iso8601)
+
+end_date = plan.end_date || (Time.now + 2.years)
+json.end end_date&.to_formatted_s(:iso8601)
+
+if plan.funder.present? || plan.grant_id.present?
+ json.funding [plan] do
+ json.partial! 'api/v2/plans/funding', plan: plan
+ end
+end
diff --git a/app/views/api/v2/plans/_show.json.jbuilder b/app/views/api/v2/plans/_show.json.jbuilder
new file mode 100644
index 0000000000..0de52775a3
--- /dev/null
+++ b/app/views/api/v2/plans/_show.json.jbuilder
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+# locals: plan
+
+json.schema 'https://github.com/RDA-DMP-Common/RDA-DMP-Common-Standard/tree/master/examples/JSON/JSON-schema/1.0'
+
+presenter = Api::V2::PlanPresenter.new(plan: plan)
+
+# Note the symbol of the dmproadmap json object
+# nested in extensions which is the container for the json template object, etc.
+
+# A JSON representation of a Data Management Plan in the
+# RDA Common Standard format
+json.title plan.title
+json.description plan.description
+json.language Api::V2::LanguagePresenter.three_char_code(
+ lang: LocaleService.default_locale
+)
+json.created plan.created_at.to_formatted_s(:iso8601)
+json.modified plan.updated_at.to_formatted_s(:iso8601)
+
+json.ethical_issues_exist Api::V2::ConversionService.boolean_to_yes_no_unknown(plan.ethical_issues)
+json.ethical_issues_description plan.ethical_issues_description
+json.ethical_issues_report plan.ethical_issues_report
+
+id = presenter.identifier
+if id.present?
+ json.dmp_id do
+ json.partial! 'api/v2/identifiers/show', identifier: id
+ end
+end
+
+if presenter.data_contact.present?
+ json.contact do
+ json.partial! 'api/v2/contributors/show', contributor: presenter.data_contact,
+ is_contact: true
+ end
+end
+
+unless @minimal
+ if presenter.contributors.any?
+ json.contributor presenter.contributors do |contributor|
+ json.partial! 'api/v2/contributors/show', contributor: contributor,
+ is_contact: false
+ end
+ end
+
+ if presenter.costs.any?
+ json.cost presenter.costs do |cost|
+ json.partial! 'api/v2/plans/cost', cost: cost
+ end
+ end
+
+ json.project [plan] do |pln|
+ json.partial! 'api/v2/plans/project', plan: pln
+ end
+
+ outputs = plan.research_outputs.any? ? plan.research_outputs : [plan]
+
+ json.dataset outputs do |output|
+ json.partial! "api/v2/datasets/show", output: output
+ end
+
+ json.extension [plan.template] do |template|
+ json.set! :dmproadmap do
+ json.template do
+ json.id template.id
+ json.title template.title
+ end
+ end
+ end
+end
diff --git a/app/views/api/v2/plans/index.json.jbuilder b/app/views/api/v2/plans/index.json.jbuilder
new file mode 100644
index 0000000000..f19f41d1dc
--- /dev/null
+++ b/app/views/api/v2/plans/index.json.jbuilder
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+json.partial! 'api/v2/standard_response', total_items: @total_items
+
+json.items @items do |item|
+ json.dmp do
+ json.partial! 'api/v2/plans/show', plan: item
+ end
+end
diff --git a/app/views/api/v2/templates/index.json.jbuilder b/app/views/api/v2/templates/index.json.jbuilder
new file mode 100644
index 0000000000..cdb35f54fb
--- /dev/null
+++ b/app/views/api/v2/templates/index.json.jbuilder
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+json.partial! 'api/v2/standard_response', total_items: @total_items
+
+json.items @items do |template|
+ presenter = Api::V2::TemplatePresenter.new(template: template)
+
+ json.dmp_template do
+ json.title presenter.title
+ json.description template.description
+ json.version template.version
+ json.created template.created_at.to_formatted_s(:iso8601)
+ json.modified template.updated_at.to_formatted_s(:iso8601)
+
+ json.affiliation do
+ json.partial! 'api/v2/orgs/show', org: template.org
+ end
+
+ json.template_id do
+ identifier = Api::V2::ConversionService.to_identifier(context: @application,
+ value: template.id)
+ json.partial! 'api/v2/identifiers/show', identifier: identifier
+ end
+ end
+end
diff --git a/app/views/doorkeeper/applications/_delete_form.html.erb b/app/views/doorkeeper/applications/_delete_form.html.erb
new file mode 100644
index 0000000000..b6377d35f5
--- /dev/null
+++ b/app/views/doorkeeper/applications/_delete_form.html.erb
@@ -0,0 +1,6 @@
+<%- submit_btn_css ||= 'btn btn-link' %>
+<%= form_tag oauth_application_path(application), method: :delete do %>
+ <%= submit_tag t('doorkeeper.applications.buttons.destroy'),
+ onclick: "return confirm('#{ t('doorkeeper.applications.confirmations.destroy') }')",
+ class: submit_btn_css, style: "border-radius: 0;" %>
+<% end %>
\ No newline at end of file
diff --git a/app/views/doorkeeper/applications/_form.html.erb b/app/views/doorkeeper/applications/_form.html.erb
new file mode 100644
index 0000000000..5aeeeaf9ab
--- /dev/null
+++ b/app/views/doorkeeper/applications/_form.html.erb
@@ -0,0 +1,42 @@
+<%= form_for application, url: doorkeeper_submit_path(application), as: :doorkeeper_application, html: { role: 'form' } do |f| %>
+ <% if application.errors.any? %>
+
<%= t('doorkeeper.applications.form.error') %>
+ <% end %>
+
+
+
+
+
+
+
+
+<% end %>
\ No newline at end of file
diff --git a/app/views/doorkeeper/applications/edit.html.erb b/app/views/doorkeeper/applications/edit.html.erb
new file mode 100644
index 0000000000..95fb9ab2d5
--- /dev/null
+++ b/app/views/doorkeeper/applications/edit.html.erb
@@ -0,0 +1,5 @@
+
+
<%= t('.title') %>
+
+
+<%= render 'form', application: @application %>
\ No newline at end of file
diff --git a/app/views/doorkeeper/applications/index.html.erb b/app/views/doorkeeper/applications/index.html.erb
new file mode 100644
index 0000000000..835e0d917f
--- /dev/null
+++ b/app/views/doorkeeper/applications/index.html.erb
@@ -0,0 +1,34 @@
+
+
<%= t('.title') %>
+
+
+<%= link_to t('.new'), new_oauth_application_path, class: 'btn btn-secondary', style: "border-radius: 0;" %>
+
+
+
+
+ | <%= t('.name') %> |
+ <%= t('.callback_url') %> |
+ <%= t('.actions') %> |
+ |
+
+
+
+ <% @applications.each do |application| %>
+
+ |
+ <%= link_to application.name, oauth_application_path(application) %>
+ |
+
+ <%= simple_format(application.redirect_uri) %>
+ |
+
+ <%= link_to t('doorkeeper.applications.buttons.edit'), edit_oauth_application_path(application), class: 'btn btn-link' %>
+ |
+
+ <%= render 'delete_form', application: application %>
+ |
+
+ <% end %>
+
+
\ No newline at end of file
diff --git a/app/views/doorkeeper/applications/new.html.erb b/app/views/doorkeeper/applications/new.html.erb
new file mode 100644
index 0000000000..95fb9ab2d5
--- /dev/null
+++ b/app/views/doorkeeper/applications/new.html.erb
@@ -0,0 +1,5 @@
+
+
<%= t('.title') %>
+
+
+<%= render 'form', application: @application %>
\ No newline at end of file
diff --git a/app/views/doorkeeper/applications/show.html.erb b/app/views/doorkeeper/applications/show.html.erb
new file mode 100644
index 0000000000..71e06b573e
--- /dev/null
+++ b/app/views/doorkeeper/applications/show.html.erb
@@ -0,0 +1,42 @@
+<%= fields_for @application, as: :doorkeeper_application, html: { role: 'form' } do |f| %>
+
+
+
+
+
+
+
+
+
+
+
+<% end %>
\ No newline at end of file
diff --git a/app/views/doorkeeper/authorizations/error.html.erb b/app/views/doorkeeper/authorizations/error.html.erb
new file mode 100644
index 0000000000..4173caf8f2
--- /dev/null
+++ b/app/views/doorkeeper/authorizations/error.html.erb
@@ -0,0 +1,9 @@
+
+
<%= t('doorkeeper.authorizations.error.title') %>
+
+
+
+
+ <%= (local_assigns[:error_response] ? error_response : @pre_auth.error_response).body[:error_description] %>
+
+
\ No newline at end of file
diff --git a/app/views/doorkeeper/authorizations/form_post.html.erb b/app/views/doorkeeper/authorizations/form_post.html.erb
new file mode 100644
index 0000000000..4b0df6c0c6
--- /dev/null
+++ b/app/views/doorkeeper/authorizations/form_post.html.erb
@@ -0,0 +1,15 @@
+
+
+<%= form_tag @pre_auth.redirect_uri, method: :post, name: :redirect_form, authenticity_token: false do %>
+ <% auth.body.compact.each do |key, value| %>
+ <%= hidden_field_tag key, value %>
+ <% end %>
+<% end %>
+
+
\ No newline at end of file
diff --git a/app/views/doorkeeper/authorizations/new.html.erb b/app/views/doorkeeper/authorizations/new.html.erb
new file mode 100644
index 0000000000..c7b8d0f224
--- /dev/null
+++ b/app/views/doorkeeper/authorizations/new.html.erb
@@ -0,0 +1,46 @@
+
+
+
+
+ <%= raw t('.prompt', client_name: content_tag(:strong, class: 'text-info') { @pre_auth.client.name }) %>
+
+
+ <% if @pre_auth.scopes.count > 0 %>
+
+
<%= t('.able_to') %>:
+
+
+ <% @pre_auth.scopes.each do |scope| %>
+ - <%= t(scope, scope: [:doorkeeper, :scopes]) + " your plans" %>
+ <% end %>
+
+
+ <% end %>
+
+
+ <%= form_tag oauth_authorization_path, method: :post do %>
+ <%= hidden_field_tag :client_id, @pre_auth.client.uid, id: nil %>
+ <%= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri, id: nil %>
+ <%= hidden_field_tag :state, @pre_auth.state, id: nil %>
+ <%= hidden_field_tag :response_type, @pre_auth.response_type, id: nil %>
+ <%= hidden_field_tag :response_mode, @pre_auth.response_mode, id: nil %>
+ <%= hidden_field_tag :scope, @pre_auth.scope, id: nil %>
+ <%= hidden_field_tag :code_challenge, @pre_auth.code_challenge, id: nil %>
+ <%= hidden_field_tag :code_challenge_method, @pre_auth.code_challenge_method, id: nil %>
+ <%= submit_tag t('doorkeeper.authorizations.buttons.authorize'), class: "btn btn-success mt-3 mb-3", style: "border-radius: 0;" %>
+ <% end %>
+ <%= form_tag oauth_authorization_path, method: :delete do %>
+ <%= hidden_field_tag :client_id, @pre_auth.client.uid, id: nil %>
+ <%= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri, id: nil %>
+ <%= hidden_field_tag :state, @pre_auth.state, id: nil %>
+ <%= hidden_field_tag :response_type, @pre_auth.response_type, id: nil %>
+ <%= hidden_field_tag :response_mode, @pre_auth.response_mode, id: nil %>
+ <%= hidden_field_tag :scope, @pre_auth.scope, id: nil %>
+ <%= hidden_field_tag :code_challenge, @pre_auth.code_challenge, id: nil %>
+ <%= hidden_field_tag :code_challenge_method, @pre_auth.code_challenge_method, id: nil %>
+ <%= submit_tag t('doorkeeper.authorizations.buttons.deny'), class: "btn btn-danger", style: "border-radius: 0;" %>
+ <% end %>
+
+
\ No newline at end of file
diff --git a/app/views/doorkeeper/authorizations/show.html.erb b/app/views/doorkeeper/authorizations/show.html.erb
new file mode 100644
index 0000000000..385fc9f24b
--- /dev/null
+++ b/app/views/doorkeeper/authorizations/show.html.erb
@@ -0,0 +1,7 @@
+
+
+
+ <%= params[:code] %>
+
\ No newline at end of file
diff --git a/app/views/doorkeeper/authorized_applications/_delete_form.html.erb b/app/views/doorkeeper/authorized_applications/_delete_form.html.erb
new file mode 100644
index 0000000000..b39ef93edb
--- /dev/null
+++ b/app/views/doorkeeper/authorized_applications/_delete_form.html.erb
@@ -0,0 +1,4 @@
+<%- submit_btn_css ||= 'btn btn-link' %>
+<%= form_tag oauth_authorized_application_path(application), method: :delete do %>
+ <%= submit_tag t('doorkeeper.authorized_applications.buttons.revoke'), onclick: "return confirm('#{ t('doorkeeper.authorized_applications.confirmations.revoke') }')", class: submit_btn_css %>
+<% end %>
\ No newline at end of file
diff --git a/app/views/doorkeeper/authorized_applications/index.html.erb b/app/views/doorkeeper/authorized_applications/index.html.erb
new file mode 100644
index 0000000000..08e8429fd2
--- /dev/null
+++ b/app/views/doorkeeper/authorized_applications/index.html.erb
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+ | <%= t('doorkeeper.authorized_applications.index.application') %> |
+ <%= t('doorkeeper.authorized_applications.index.created_at') %> |
+ |
+
+
+
+ <% @applications.each do |application| %>
+
+ | <%= application.name %> |
+ <%= application.created_at.strftime(t('doorkeeper.authorized_applications.index.date_format')) %> |
+ <%= render 'delete_form', application: application %> |
+
+ <% end %>
+
+
+
\ No newline at end of file
diff --git a/config/application.rb b/config/application.rb
index 882ebb0def..db4975c352 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -53,5 +53,12 @@ class Application < Rails::Application
# Set the default host for mailer URLs
config.action_mailer.default_url_options = { host: Socket.gethostname.to_s }
+
+ # apply application styling to doorkeeper views
+ config.to_prepare do
+ Doorkeeper::ApplicationsController.layout "application"
+ Doorkeeper::AuthorizationsController.layout "application"
+ Doorkeeper::AuthorizedApplicationsController.layout "application"
+ end
end
end
diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb
new file mode 100644
index 0000000000..a7da6540f0
--- /dev/null
+++ b/config/initializers/doorkeeper.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+Doorkeeper.configure do # rubocop:todo Metrics/BlockLength
+ # set the object-relational-model (ORM)
+ orm :active_record
+
+ # ensure resource owner is authenticated
+ resource_owner_authenticator do
+ if user_signed_in?
+ if request.path == "/oauth/authorize/native"
+ # the /oauth/authorize/native path is only used for mobile devices
+ # and so it is better to deactivate it
+ redirect_to root_path, alert: "You are not authorized to perform this action."
+ else
+ current_user
+ end
+ else
+ # preserve oauth2 request url before redirecting to login
+ session[:user_return_to] = request.fullpath if request.get?
+
+ # redirect user to login page
+ redirect_to new_user_session_url
+ end
+ end
+
+ # ensure only super-admins can manage oauth applications
+ admin_authenticator do |_routes|
+ if current_user
+ unless current_user.can_super_admin?
+ redirect_to root_path, alert: "You are not authorized to perform this action."
+ end
+ else
+ warden.authenticate!(scope: :user)
+ end
+ end
+
+ # grant flows enabled
+ # Authorization Code Grant Flow (ACGF)
+ grant_flows %w[authorization_code client_credentials]
+
+ # allow for redirect-uri to be blank
+ # (required for client_credentials apps for org-admins)
+ allow_blank_redirect_uri true
+
+ # scopes enabled
+ default_scopes :read
+
+ # ensure client apps cannot ask for scopes outwith those specified here
+ enforce_configured_scopes
+
+ # set the token endpoint configurations
+ access_token_expires_in 2.hours
+ reuse_access_token
+
+ # enable refresh tokens of duration 90 days
+ use_refresh_token expiry: 90.days
+
+ # enable ssl requirement for redirect url
+ force_ssl_in_redirect_uri true
+end
diff --git a/config/locale/app.pot b/config/locale/app.pot
index 2d2bda03d4..24563216d5 100644
--- a/config/locale/app.pot
+++ b/config/locale/app.pot
@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: roadmap_upstream 1.0\n"
"Report-Msgid-Bugs-To: contact@translation.io\n"
-"POT-Creation-Date: 2025-04-10 13:28-0600\n"
-"PO-Revision-Date: 2025-04-10 13:28-0600\n"
+"POT-Creation-Date: 2025-12-23 08:33-0700\n"
+"PO-Revision-Date: 2025-12-23 08:33-0700\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
"Language: \n"
@@ -123,87 +123,95 @@ msgstr ""
msgid "No Plans found"
msgstr ""
-#: ../../app/controllers/application_controller.rb:36
+#: ../../app/controllers/api/v2/base_api_controller.rb:72
+msgid "There was a problem in the server."
+msgstr ""
+
+#: ../../app/controllers/api/v2/base_api_controller.rb:78
+msgid "The client is not authorized to perform this action."
+msgstr ""
+
+#: ../../app/controllers/application_controller.rb:37
msgid "You are not authorized to perform this action."
msgstr ""
-#: ../../app/controllers/application_controller.rb:40
+#: ../../app/controllers/application_controller.rb:41
msgid "You need to sign in or sign up before continuing."
msgstr ""
-#: ../../app/controllers/application_controller.rb:108
+#: ../../app/controllers/application_controller.rb:115
msgid "Unable to %{action} the %{object}. %{errors}"
msgstr ""
-#: ../../app/controllers/application_controller.rb:114
+#: ../../app/controllers/application_controller.rb:121
msgid "Successfully %{action} the %{object}."
msgstr ""
-#: ../../app/controllers/application_controller.rb:127
+#: ../../app/controllers/application_controller.rb:134
msgid "API client"
msgstr ""
-#: ../../app/controllers/application_controller.rb:128
+#: ../../app/controllers/application_controller.rb:135
msgid "plan"
msgstr ""
-#: ../../app/controllers/application_controller.rb:129
+#: ../../app/controllers/application_controller.rb:136
msgid "guidance group"
msgstr ""
-#: ../../app/controllers/application_controller.rb:130
+#: ../../app/controllers/application_controller.rb:137
msgid "comment"
msgstr ""
-#: ../../app/controllers/application_controller.rb:131
+#: ../../app/controllers/application_controller.rb:138
msgid "organisation"
msgstr ""
-#: ../../app/controllers/application_controller.rb:132
+#: ../../app/controllers/application_controller.rb:139
msgid "permission"
msgstr ""
-#: ../../app/controllers/application_controller.rb:133
+#: ../../app/controllers/application_controller.rb:140
msgid "preferences"
msgstr ""
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "profile"
msgstr ""
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "user"
msgstr ""
-#: ../../app/controllers/application_controller.rb:135
+#: ../../app/controllers/application_controller.rb:142
msgid "question option"
msgstr ""
-#: ../../app/controllers/application_controller.rb:181
+#: ../../app/controllers/application_controller.rb:188
msgid "Record Not Found"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:45
+#: ../../app/controllers/concerns/paginable.rb:46
msgid "scope should be an ActiveRecord::Relation object"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:47
+#: ../../app/controllers/concerns/paginable.rb:48
msgid "path_params should be a Hash object"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:48
+#: ../../app/controllers/concerns/paginable.rb:49
msgid "query_params should be a Hash object"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:49
+#: ../../app/controllers/concerns/paginable.rb:50
msgid "locals should be a Hash object"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:70
+#: ../../app/controllers/concerns/paginable.rb:71
msgid "Restricted access to View All the records"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:183
+#: ../../app/controllers/concerns/paginable.rb:184
msgid "Sort by %{sort_field}"
msgstr ""
@@ -244,77 +252,77 @@ msgstr ""
msgid "Unable to submit your request"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:40
-#: ../../app/controllers/contributors_controller.rb:56
+#: ../../app/controllers/contributors_controller.rb:41
+#: ../../app/controllers/contributors_controller.rb:57
#: ../../app/controllers/research_outputs_controller.rb:42
msgid "add"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:54
+#: ../../app/controllers/contributors_controller.rb:55
#: ../../app/controllers/research_outputs_controller.rb:40
msgid "added"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:72
+#: ../../app/controllers/contributors_controller.rb:73
#: ../../app/controllers/guidance_groups_controller.rb:55
#: ../../app/controllers/guidances_controller.rb:75
-#: ../../app/controllers/notes_controller.rb:88
+#: ../../app/controllers/notes_controller.rb:89
#: ../../app/controllers/org_admin/departments_controller.rb:50
#: ../../app/controllers/org_admin/sections_controller.rb:103
#: ../../app/controllers/org_admin/templates_controller.rb:210
#: ../../app/controllers/orgs_controller.rb:92
-#: ../../app/controllers/plans_controller.rb:280
-#: ../../app/controllers/plans_controller.rb:283
+#: ../../app/controllers/plans_controller.rb:281
+#: ../../app/controllers/plans_controller.rb:284
#: ../../app/controllers/registrations_controller.rb:249
#: ../../app/controllers/registrations_controller.rb:253
#: ../../app/controllers/registrations_controller.rb:280
#: ../../app/controllers/registrations_controller.rb:284
#: ../../app/controllers/research_outputs_controller.rb:60
-#: ../../app/controllers/users_controller.rb:103
-#: ../../app/controllers/users_controller.rb:131
+#: ../../app/controllers/users_controller.rb:104
+#: ../../app/controllers/users_controller.rb:132
msgid "saved"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:74
+#: ../../app/controllers/contributors_controller.rb:75
#: ../../app/controllers/guidance_groups_controller.rb:57
#: ../../app/controllers/guidances_controller.rb:77
-#: ../../app/controllers/notes_controller.rb:106
+#: ../../app/controllers/notes_controller.rb:107
#: ../../app/controllers/org_admin/departments_controller.rb:52
#: ../../app/controllers/org_admin/sections_controller.rb:105
#: ../../app/controllers/org_admin/templates_controller.rb:215
#: ../../app/controllers/orgs_controller.rb:94
-#: ../../app/controllers/plans_controller.rb:289
-#: ../../app/controllers/plans_controller.rb:292
-#: ../../app/controllers/plans_controller.rb:296
-#: ../../app/controllers/plans_controller.rb:299
+#: ../../app/controllers/plans_controller.rb:290
+#: ../../app/controllers/plans_controller.rb:293
+#: ../../app/controllers/plans_controller.rb:297
+#: ../../app/controllers/plans_controller.rb:300
#: ../../app/controllers/registrations_controller.rb:256
#: ../../app/controllers/registrations_controller.rb:287
#: ../../app/controllers/research_outputs_controller.rb:63
msgid "save"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:83
-#: ../../app/controllers/notes_controller.rb:130
+#: ../../app/controllers/contributors_controller.rb:84
+#: ../../app/controllers/notes_controller.rb:131
#: ../../app/controllers/org_admin/templates_controller.rb:243
#: ../../app/controllers/research_outputs_controller.rb:74
#: ../../app/controllers/super_admin/orgs_controller.rb:94
msgid "removed"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:86
-#: ../../app/controllers/notes_controller.rb:148
+#: ../../app/controllers/contributors_controller.rb:87
+#: ../../app/controllers/notes_controller.rb:149
#: ../../app/controllers/org_admin/templates_controller.rb:245
#: ../../app/controllers/research_outputs_controller.rb:77
#: ../../app/controllers/super_admin/orgs_controller.rb:97
msgid "remove"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:160
+#: ../../app/controllers/contributors_controller.rb:161
#: ../../app/controllers/research_outputs_controller.rb:208
msgid "plan not found"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:168
+#: ../../app/controllers/contributors_controller.rb:169
msgid "contributor not found"
msgstr ""
@@ -328,7 +336,7 @@ msgstr ""
#: ../../app/controllers/guidance_groups_controller.rb:31
#: ../../app/controllers/guidances_controller.rb:53
-#: ../../app/controllers/notes_controller.rb:47
+#: ../../app/controllers/notes_controller.rb:48
#: ../../app/controllers/org_admin/departments_controller.rb:26
#: ../../app/controllers/org_admin/phases_controller.rb:121
#: ../../app/controllers/org_admin/questions_controller.rb:94
@@ -344,7 +352,7 @@ msgstr ""
#: ../../app/controllers/guidance_groups_controller.rb:34
#: ../../app/controllers/guidances_controller.rb:55
-#: ../../app/controllers/notes_controller.rb:66
+#: ../../app/controllers/notes_controller.rb:67
#: ../../app/controllers/org_admin/departments_controller.rb:30
#: ../../app/controllers/org_admin/phases_controller.rb:123
#: ../../app/controllers/org_admin/questions_controller.rb:96
@@ -383,7 +391,7 @@ msgstr ""
#: ../../app/controllers/org_admin/question_options_controller.rb:24
#: ../../app/controllers/org_admin/questions_controller.rb:197
#: ../../app/controllers/org_admin/sections_controller.rb:128
-#: ../../app/controllers/plans_controller.rb:342
+#: ../../app/controllers/plans_controller.rb:343
#: ../../app/controllers/super_admin/api_clients_controller.rb:81
#: ../../app/controllers/super_admin/notifications_controller.rb:85
#: ../../app/controllers/super_admin/themes_controller.rb:51
@@ -397,7 +405,7 @@ msgstr ""
#: ../../app/controllers/org_admin/question_options_controller.rb:26
#: ../../app/controllers/org_admin/questions_controller.rb:199
#: ../../app/controllers/org_admin/sections_controller.rb:130
-#: ../../app/controllers/plans_controller.rb:347
+#: ../../app/controllers/plans_controller.rb:348
#: ../../app/controllers/super_admin/api_clients_controller.rb:84
#: ../../app/controllers/super_admin/notifications_controller.rb:88
#: ../../app/controllers/super_admin/themes_controller.rb:54
@@ -438,19 +446,19 @@ msgstr ""
#: ../../app/controllers/org_admin/phases_controller.rb:147
#: ../../app/controllers/org_admin/questions_controller.rb:166
#: ../../app/controllers/org_admin/users_controller.rb:30
-#: ../../app/controllers/plans_controller.rb:416
+#: ../../app/controllers/plans_controller.rb:417
#: ../../app/controllers/super_admin/api_clients_controller.rb:68
#: ../../app/controllers/super_admin/notifications_controller.rb:52
#: ../../app/controllers/super_admin/themes_controller.rb:39
#: ../../app/controllers/super_admin/users_controller.rb:54
-#: ../../app/controllers/users_controller.rb:108
+#: ../../app/controllers/users_controller.rb:109
msgid "updated"
msgstr ""
#: ../../app/controllers/org_admin/phases_controller.rb:149
#: ../../app/controllers/org_admin/questions_controller.rb:169
#: ../../app/controllers/org_admin/users_controller.rb:32
-#: ../../app/controllers/plans_controller.rb:419
+#: ../../app/controllers/plans_controller.rb:420
#: ../../app/controllers/super_admin/api_clients_controller.rb:70
#: ../../app/controllers/super_admin/notifications_controller.rb:55
#: ../../app/controllers/super_admin/themes_controller.rb:41
@@ -540,7 +548,7 @@ msgid "Unable to delete this version of the template."
msgstr ""
#: ../../app/controllers/org_admin/template_copies_controller.rb:20
-#: ../../app/controllers/plans_controller.rb:395
+#: ../../app/controllers/plans_controller.rb:396
msgid "copy"
msgstr ""
@@ -549,11 +557,11 @@ msgstr ""
msgid "That template is no longer customizable."
msgstr ""
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:21
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:22
msgid "Unable to customize that template."
msgstr ""
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:24
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:25
msgid "That template is not customizable."
msgstr ""
@@ -643,33 +651,33 @@ msgstr ""
msgid "template with customisations by the"
msgstr ""
-#: ../../app/controllers/plans_controller.rb:393
+#: ../../app/controllers/plans_controller.rb:394
msgid "copied"
msgstr ""
-#: ../../app/controllers/plans_controller.rb:424
+#: ../../app/controllers/plans_controller.rb:425
msgid ""
"Unable to change the plan's status since it is needed at least %{percentage} p"
"ercentage responded"
msgstr ""
-#: ../../app/controllers/plans_controller.rb:430
+#: ../../app/controllers/plans_controller.rb:431
msgid "Unable to find plan id %{plan_id}"
msgstr ""
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is now a test."
msgstr ""
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is no longer a test."
msgstr ""
-#: ../../app/controllers/plans_controller.rb:449
+#: ../../app/controllers/plans_controller.rb:450
msgid "Unable to change the plan's test status"
msgstr ""
-#: ../../app/controllers/plans_controller.rb:462
+#: ../../app/controllers/plans_controller.rb:463
msgid "There is no plan associated with id %{s"
msgstr ""
@@ -754,7 +762,7 @@ msgstr ""
msgid "research output not found"
msgstr ""
-#: ../../app/controllers/roles_controller.rb:26
+#: ../../app/controllers/roles_controller.rb:27
msgid ""
"Cannot share plan with %{email} since that email matches\n"
" with the owner of the plan."
@@ -917,27 +925,27 @@ msgstr ""
msgid "Unable to link your account to %{scheme}."
msgstr ""
-#: ../../app/controllers/users_controller.rb:149
+#: ../../app/controllers/users_controller.rb:150
msgid "Successfully %{action} %{username}'s account."
msgstr ""
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "activated"
msgstr ""
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "deactivated"
msgstr ""
-#: ../../app/controllers/users_controller.rb:156
+#: ../../app/controllers/users_controller.rb:157
msgid "Unable to %{action} %{username}"
msgstr ""
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "activate"
msgstr ""
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "deactivate"
msgstr ""
@@ -1217,50 +1225,50 @@ msgstr ""
msgid "Last 12 months"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:17
+#: ../../app/mailers/user_mailer.rb:18
#: ../../app/views/devise/mailer/invitation_instructions.html.erb:5
#: ../../app/views/devise/mailer/reset_password_instructions.html.erb:5
#: ../../app/views/user_mailer/_email_signature.html.erb:2
msgid "Query or feedback related to %{tool_name}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:25
+#: ../../app/mailers/user_mailer.rb:26
msgid "Welcome to %{tool_name}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:62
+#: ../../app/mailers/user_mailer.rb:63
msgid "A Data Management Plan in %{tool_name} has been shared with you"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:79
+#: ../../app/mailers/user_mailer.rb:80
msgid "Changed permissions on a Data Management Plan in %{tool_name}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:94
+#: ../../app/mailers/user_mailer.rb:95
msgid "Permissions removed on a DMP in %{tool_name}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:112
+#: ../../app/mailers/user_mailer.rb:113
msgid "%{user_name} has requested feedback on a %{tool_name} plan"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:135
+#: ../../app/mailers/user_mailer.rb:136
msgid "%{tool_name}: Expert feedback has been provided for %{plan_title}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:153
+#: ../../app/mailers/user_mailer.rb:154
msgid "DMP Visibility Changed: %{plan_title}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:182
+#: ../../app/mailers/user_mailer.rb:183
msgid "%{tool_name}: A new comment was added to %{plan_title}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:198
+#: ../../app/mailers/user_mailer.rb:199
msgid "Administrator privileges granted in %{tool_name}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:216
+#: ../../app/mailers/user_mailer.rb:217
msgid "%{tool_name} API changes"
msgstr ""
@@ -1490,15 +1498,15 @@ msgstr ""
msgid "already assigned a value"
msgstr ""
-#: ../../app/models/org.rb:46
+#: ../../app/models/org.rb:47
msgid "Feedback email message"
msgstr ""
-#: ../../app/models/org.rb:123
+#: ../../app/models/org.rb:124
msgid "must be one of the following formats: jpeg, jpg, png, gif, bmp"
msgstr ""
-#: ../../app/models/org.rb:128
+#: ../../app/models/org.rb:129
msgid "can't be larger than 500KB"
msgstr ""
@@ -1622,7 +1630,7 @@ msgstr ""
msgid "Conditions in the template refer backwards"
msgstr ""
-#: ../../app/models/user.rb:380
+#: ../../app/models/user.rb:386
msgid "A Data Management Plan in %{application_name} has been shared with you"
msgstr ""
@@ -2032,7 +2040,7 @@ msgstr ""
#: ../../app/views/paginable/templates/_organisational.html.erb:87
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:29
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:36
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
#: ../../app/views/static_pages/about_us.html.erb:22
#: ../../app/views/static_pages/about_us.html.erb:29
#: ../../app/views/static_pages/termsuse.html.erb:46
@@ -4351,7 +4359,7 @@ msgstr ""
msgid "Instructions"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:6
+#: ../../app/views/plans/_download_form.html.erb:5
msgid "Format"
msgstr ""
@@ -4359,71 +4367,71 @@ msgstr ""
msgid "Download settings"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:19
-msgid "Select phase to download"
-msgstr ""
-
-#: ../../app/views/plans/_download_form.html.erb:26
+#: ../../app/views/plans/_download_form.html.erb:21
msgid "Optional plan components"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:30
+#: ../../app/views/plans/_download_form.html.erb:25
msgid "project details coversheet"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:36
+#: ../../app/views/plans/_download_form.html.erb:31
msgid "question text and section headings"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:42
+#: ../../app/views/plans/_download_form.html.erb:37
msgid "unanswered questions"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:49
+#: ../../app/views/plans/_download_form.html.erb:44
msgid "research outputs"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:57
+#: ../../app/views/plans/_download_form.html.erb:52
msgid "supplementary section(s) not requested by funding organisation"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:65
+#: ../../app/views/plans/_download_form.html.erb:61
+msgid "Select phase to download"
+msgstr ""
+
+#: ../../app/views/plans/_download_form.html.erb:70
msgid "PDF formatting"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:68
+#: ../../app/views/plans/_download_form.html.erb:73
msgid "Font"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:71
+#: ../../app/views/plans/_download_form.html.erb:76
msgid "Margin (mm)"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:76
+#: ../../app/views/plans/_download_form.html.erb:81
msgid "Face"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:84
+#: ../../app/views/plans/_download_form.html.erb:89
msgid "Size"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:92
+#: ../../app/views/plans/_download_form.html.erb:96
msgid "Top"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:101
+#: ../../app/views/plans/_download_form.html.erb:105
msgid "Bottom"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:110
+#: ../../app/views/plans/_download_form.html.erb:114
msgid "Left"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:119
+#: ../../app/views/plans/_download_form.html.erb:123
msgid "Right"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
msgid ""
"Download Plan (new window)%{open_in_new_window_text}"
diff --git a/config/locale/de/LC_MESSAGES/app.mo b/config/locale/de/LC_MESSAGES/app.mo
index 24a717f3c7..7d1cecb7bc 100644
Binary files a/config/locale/de/LC_MESSAGES/app.mo and b/config/locale/de/LC_MESSAGES/app.mo differ
diff --git a/config/locale/de/app.po b/config/locale/de/app.po
index ec4ab0e7b8..2c4dae7d3c 100644
--- a/config/locale/de/app.po
+++ b/config/locale/de/app.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: roadmap_upstream 1.0\n"
"Report-Msgid-Bugs-To: contact@translation.io\n"
-"POT-Creation-Date: 2025-04-10 13:28-0600\n"
-"PO-Revision-Date: 2025-04-10 21:28+0200\n"
+"POT-Creation-Date: 2025-12-23 08:33-0700\n"
+"PO-Revision-Date: 2025-12-23 15:33+0000\n"
"Last-Translator: FULL NAME \n"
"Language-Team: German\n"
"Language: de\n"
@@ -129,87 +129,95 @@ msgstr "Ungültiger JSON"
msgid "No Plans found"
msgstr "Keine Pläne gefunden"
-#: ../../app/controllers/application_controller.rb:36
+#: ../../app/controllers/api/v2/base_api_controller.rb:72
+msgid "There was a problem in the server."
+msgstr ""
+
+#: ../../app/controllers/api/v2/base_api_controller.rb:78
+msgid "The client is not authorized to perform this action."
+msgstr ""
+
+#: ../../app/controllers/application_controller.rb:37
msgid "You are not authorized to perform this action."
msgstr "Sie sind nicht berechtigt, diese Aktion durchzuführen."
-#: ../../app/controllers/application_controller.rb:40
+#: ../../app/controllers/application_controller.rb:41
msgid "You need to sign in or sign up before continuing."
msgstr "Bitte melden Sie sich an oder registrieren Sie sich bevor Sie fortfahren."
-#: ../../app/controllers/application_controller.rb:108
+#: ../../app/controllers/application_controller.rb:115
msgid "Unable to %{action} the %{object}. %{errors}"
msgstr "%{action} %{object} kann nicht ausgeführt werden. %{errors}"
-#: ../../app/controllers/application_controller.rb:114
+#: ../../app/controllers/application_controller.rb:121
msgid "Successfully %{action} the %{object}."
msgstr "Erfolgreich %{action} das %{object}."
-#: ../../app/controllers/application_controller.rb:127
+#: ../../app/controllers/application_controller.rb:134
msgid "API client"
msgstr "API-Client"
-#: ../../app/controllers/application_controller.rb:128
+#: ../../app/controllers/application_controller.rb:135
msgid "plan"
msgstr "Plan"
-#: ../../app/controllers/application_controller.rb:129
+#: ../../app/controllers/application_controller.rb:136
msgid "guidance group"
msgstr "Hinweisgruppe"
-#: ../../app/controllers/application_controller.rb:130
+#: ../../app/controllers/application_controller.rb:137
msgid "comment"
msgstr "Kommentar"
-#: ../../app/controllers/application_controller.rb:131
+#: ../../app/controllers/application_controller.rb:138
msgid "organisation"
msgstr "Organisation"
-#: ../../app/controllers/application_controller.rb:132
+#: ../../app/controllers/application_controller.rb:139
msgid "permission"
msgstr "Berechtigung"
-#: ../../app/controllers/application_controller.rb:133
+#: ../../app/controllers/application_controller.rb:140
msgid "preferences"
msgstr "Einstellungen"
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "profile"
msgstr "Profil"
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "user"
msgstr "Nutzer/in"
-#: ../../app/controllers/application_controller.rb:135
+#: ../../app/controllers/application_controller.rb:142
msgid "question option"
msgstr "Frage Option"
-#: ../../app/controllers/application_controller.rb:181
+#: ../../app/controllers/application_controller.rb:188
msgid "Record Not Found"
msgstr "Aufnahme nicht gefunden"
-#: ../../app/controllers/concerns/paginable.rb:45
+#: ../../app/controllers/concerns/paginable.rb:46
msgid "scope should be an ActiveRecord::Relation object"
msgstr "Der Bereich sollte ein ActiveRecord :: Relation-Objekt sein"
-#: ../../app/controllers/concerns/paginable.rb:47
+#: ../../app/controllers/concerns/paginable.rb:48
msgid "path_params should be a Hash object"
msgstr "path_params sollte ein Hash-Objekt sein"
-#: ../../app/controllers/concerns/paginable.rb:48
+#: ../../app/controllers/concerns/paginable.rb:49
msgid "query_params should be a Hash object"
msgstr "query_params sollte ein Hash-Objekt sein"
-#: ../../app/controllers/concerns/paginable.rb:49
+#: ../../app/controllers/concerns/paginable.rb:50
msgid "locals should be a Hash object"
msgstr "Einheimische sollten ein Hash-Objekt sein"
-#: ../../app/controllers/concerns/paginable.rb:70
+#: ../../app/controllers/concerns/paginable.rb:71
msgid "Restricted access to View All the records"
msgstr "Eingeschränkter Zugriff auf Alle Datensätze anzeigen"
-#: ../../app/controllers/concerns/paginable.rb:183
+#: ../../app/controllers/concerns/paginable.rb:184
msgid "Sort by %{sort_field}"
msgstr "Sortieren nach %{sort_field}"
@@ -252,77 +260,77 @@ msgstr "Die Nachricht wurde erfolgreich versendet."
msgid "Unable to submit your request"
msgstr "Ihre Anfrage konnte nicht gesendet werden"
-#: ../../app/controllers/contributors_controller.rb:40
-#: ../../app/controllers/contributors_controller.rb:56
+#: ../../app/controllers/contributors_controller.rb:41
+#: ../../app/controllers/contributors_controller.rb:57
#: ../../app/controllers/research_outputs_controller.rb:42
msgid "add"
msgstr "Hinzufügen"
-#: ../../app/controllers/contributors_controller.rb:54
+#: ../../app/controllers/contributors_controller.rb:55
#: ../../app/controllers/research_outputs_controller.rb:40
msgid "added"
msgstr "Hinzugefügt"
-#: ../../app/controllers/contributors_controller.rb:72
+#: ../../app/controllers/contributors_controller.rb:73
#: ../../app/controllers/guidance_groups_controller.rb:55
#: ../../app/controllers/guidances_controller.rb:75
-#: ../../app/controllers/notes_controller.rb:88
+#: ../../app/controllers/notes_controller.rb:89
#: ../../app/controllers/org_admin/departments_controller.rb:50
#: ../../app/controllers/org_admin/sections_controller.rb:103
#: ../../app/controllers/org_admin/templates_controller.rb:210
#: ../../app/controllers/orgs_controller.rb:92
-#: ../../app/controllers/plans_controller.rb:280
-#: ../../app/controllers/plans_controller.rb:283
+#: ../../app/controllers/plans_controller.rb:281
+#: ../../app/controllers/plans_controller.rb:284
#: ../../app/controllers/registrations_controller.rb:249
#: ../../app/controllers/registrations_controller.rb:253
#: ../../app/controllers/registrations_controller.rb:280
#: ../../app/controllers/registrations_controller.rb:284
#: ../../app/controllers/research_outputs_controller.rb:60
-#: ../../app/controllers/users_controller.rb:103
-#: ../../app/controllers/users_controller.rb:131
+#: ../../app/controllers/users_controller.rb:104
+#: ../../app/controllers/users_controller.rb:132
msgid "saved"
msgstr "gespeichert"
-#: ../../app/controllers/contributors_controller.rb:74
+#: ../../app/controllers/contributors_controller.rb:75
#: ../../app/controllers/guidance_groups_controller.rb:57
#: ../../app/controllers/guidances_controller.rb:77
-#: ../../app/controllers/notes_controller.rb:106
+#: ../../app/controllers/notes_controller.rb:107
#: ../../app/controllers/org_admin/departments_controller.rb:52
#: ../../app/controllers/org_admin/sections_controller.rb:105
#: ../../app/controllers/org_admin/templates_controller.rb:215
#: ../../app/controllers/orgs_controller.rb:94
-#: ../../app/controllers/plans_controller.rb:289
-#: ../../app/controllers/plans_controller.rb:292
-#: ../../app/controllers/plans_controller.rb:296
-#: ../../app/controllers/plans_controller.rb:299
+#: ../../app/controllers/plans_controller.rb:290
+#: ../../app/controllers/plans_controller.rb:293
+#: ../../app/controllers/plans_controller.rb:297
+#: ../../app/controllers/plans_controller.rb:300
#: ../../app/controllers/registrations_controller.rb:256
#: ../../app/controllers/registrations_controller.rb:287
#: ../../app/controllers/research_outputs_controller.rb:63
msgid "save"
msgstr "Speichern"
-#: ../../app/controllers/contributors_controller.rb:83
-#: ../../app/controllers/notes_controller.rb:130
+#: ../../app/controllers/contributors_controller.rb:84
+#: ../../app/controllers/notes_controller.rb:131
#: ../../app/controllers/org_admin/templates_controller.rb:243
#: ../../app/controllers/research_outputs_controller.rb:74
#: ../../app/controllers/super_admin/orgs_controller.rb:94
msgid "removed"
msgstr "entfernt"
-#: ../../app/controllers/contributors_controller.rb:86
-#: ../../app/controllers/notes_controller.rb:148
+#: ../../app/controllers/contributors_controller.rb:87
+#: ../../app/controllers/notes_controller.rb:149
#: ../../app/controllers/org_admin/templates_controller.rb:245
#: ../../app/controllers/research_outputs_controller.rb:77
#: ../../app/controllers/super_admin/orgs_controller.rb:97
msgid "remove"
msgstr "entfernen"
-#: ../../app/controllers/contributors_controller.rb:160
+#: ../../app/controllers/contributors_controller.rb:161
#: ../../app/controllers/research_outputs_controller.rb:208
msgid "plan not found"
msgstr "Plan nicht gefunden"
-#: ../../app/controllers/contributors_controller.rb:168
+#: ../../app/controllers/contributors_controller.rb:169
msgid "contributor not found"
msgstr "Mitwirkender nicht gefunden"
@@ -336,7 +344,7 @@ msgstr "Bei der Anforderung von Feedback für diesen Plan ist ein Fehler aufgetr
#: ../../app/controllers/guidance_groups_controller.rb:31
#: ../../app/controllers/guidances_controller.rb:53
-#: ../../app/controllers/notes_controller.rb:47
+#: ../../app/controllers/notes_controller.rb:48
#: ../../app/controllers/org_admin/departments_controller.rb:26
#: ../../app/controllers/org_admin/phases_controller.rb:121
#: ../../app/controllers/org_admin/questions_controller.rb:94
@@ -352,7 +360,7 @@ msgstr "Erstellt"
#: ../../app/controllers/guidance_groups_controller.rb:34
#: ../../app/controllers/guidances_controller.rb:55
-#: ../../app/controllers/notes_controller.rb:66
+#: ../../app/controllers/notes_controller.rb:67
#: ../../app/controllers/org_admin/departments_controller.rb:30
#: ../../app/controllers/org_admin/phases_controller.rb:123
#: ../../app/controllers/org_admin/questions_controller.rb:96
@@ -395,7 +403,7 @@ msgstr "Veröffentlichung zurückziehen"
#: ../../app/controllers/org_admin/question_options_controller.rb:24
#: ../../app/controllers/org_admin/questions_controller.rb:197
#: ../../app/controllers/org_admin/sections_controller.rb:128
-#: ../../app/controllers/plans_controller.rb:342
+#: ../../app/controllers/plans_controller.rb:343
#: ../../app/controllers/super_admin/api_clients_controller.rb:81
#: ../../app/controllers/super_admin/notifications_controller.rb:85
#: ../../app/controllers/super_admin/themes_controller.rb:51
@@ -409,7 +417,7 @@ msgstr "Gelöscht"
#: ../../app/controllers/org_admin/question_options_controller.rb:26
#: ../../app/controllers/org_admin/questions_controller.rb:199
#: ../../app/controllers/org_admin/sections_controller.rb:130
-#: ../../app/controllers/plans_controller.rb:347
+#: ../../app/controllers/plans_controller.rb:348
#: ../../app/controllers/super_admin/api_clients_controller.rb:84
#: ../../app/controllers/super_admin/notifications_controller.rb:88
#: ../../app/controllers/super_admin/themes_controller.rb:54
@@ -454,19 +462,19 @@ msgstr "Es kann keine neue Version dieser Vorlage erstellt werden.
"
#: ../../app/controllers/org_admin/phases_controller.rb:147
#: ../../app/controllers/org_admin/questions_controller.rb:166
#: ../../app/controllers/org_admin/users_controller.rb:30
-#: ../../app/controllers/plans_controller.rb:416
+#: ../../app/controllers/plans_controller.rb:417
#: ../../app/controllers/super_admin/api_clients_controller.rb:68
#: ../../app/controllers/super_admin/notifications_controller.rb:52
#: ../../app/controllers/super_admin/themes_controller.rb:39
#: ../../app/controllers/super_admin/users_controller.rb:54
-#: ../../app/controllers/users_controller.rb:108
+#: ../../app/controllers/users_controller.rb:109
msgid "updated"
msgstr "aktualisiert"
#: ../../app/controllers/org_admin/phases_controller.rb:149
#: ../../app/controllers/org_admin/questions_controller.rb:169
#: ../../app/controllers/org_admin/users_controller.rb:32
-#: ../../app/controllers/plans_controller.rb:419
+#: ../../app/controllers/plans_controller.rb:420
#: ../../app/controllers/super_admin/api_clients_controller.rb:70
#: ../../app/controllers/super_admin/notifications_controller.rb:55
#: ../../app/controllers/super_admin/themes_controller.rb:41
@@ -562,7 +570,7 @@ msgid "Unable to delete this version of the template."
msgstr "Diese Version der Vorlage kann nicht gelöscht werden."
#: ../../app/controllers/org_admin/template_copies_controller.rb:20
-#: ../../app/controllers/plans_controller.rb:395
+#: ../../app/controllers/plans_controller.rb:396
msgid "copy"
msgstr "Kopieren"
@@ -571,11 +579,11 @@ msgstr "Kopieren"
msgid "That template is no longer customizable."
msgstr "Diese Vorlage ist nicht mehr anpassbar."
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:21
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:22
msgid "Unable to customize that template."
msgstr "Diese Vorlage kann nicht angepasst werden."
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:24
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:25
msgid "That template is not customizable."
msgstr "Diese Vorlage ist nicht anpassbar."
@@ -667,11 +675,11 @@ msgstr "Dieser Plan basiert auf dem"
msgid "template with customisations by the"
msgstr "Vorlage mit Anpassungen durch die"
-#: ../../app/controllers/plans_controller.rb:393
+#: ../../app/controllers/plans_controller.rb:394
msgid "copied"
msgstr "Kopiert"
-#: ../../app/controllers/plans_controller.rb:424
+#: ../../app/controllers/plans_controller.rb:425
msgid ""
"Unable to change the plan's status since it is needed at least %{percentage} p"
"ercentage responded"
@@ -679,23 +687,23 @@ msgstr ""
"Der Status des Plans konnte nicht geändert werden, da mindestens %{percentage}"
" Prozentsatz angefordert wurde"
-#: ../../app/controllers/plans_controller.rb:430
+#: ../../app/controllers/plans_controller.rb:431
msgid "Unable to find plan id %{plan_id}"
msgstr "Plan-ID konnte nicht gefunden werden %{plan_id}"
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is now a test."
msgstr "Ihr Projekt ist jetzt ein Test."
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is no longer a test."
msgstr "Ihr Projekt ist kein Test mehr."
-#: ../../app/controllers/plans_controller.rb:449
+#: ../../app/controllers/plans_controller.rb:450
msgid "Unable to change the plan's test status"
msgstr "Der Teststatus des Plans konnte nicht geändert werden"
-#: ../../app/controllers/plans_controller.rb:462
+#: ../../app/controllers/plans_controller.rb:463
msgid "There is no plan associated with id %{s"
msgstr "ID %{ ist kein Plan zugeordnet S"
@@ -792,7 +800,7 @@ msgstr "Passwort und Bestätigung müssen übereinstimmen"
msgid "research output not found"
msgstr "Forschungsergebnis nicht gefunden"
-#: ../../app/controllers/roles_controller.rb:26
+#: ../../app/controllers/roles_controller.rb:27
msgid ""
"Cannot share plan with %{email} since that email matches\n"
" with the owner of the plan."
@@ -973,27 +981,27 @@ msgstr "Ihr Konto wurde erfolgreich mit %{scheme} verknüpft."
msgid "Unable to link your account to %{scheme}."
msgstr "Ihr Konto konnte nicht mit %{scheme} verknüpft werden."
-#: ../../app/controllers/users_controller.rb:149
+#: ../../app/controllers/users_controller.rb:150
msgid "Successfully %{action} %{username}'s account."
msgstr "Erfolgreich %{action} %{username} Konto."
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "activated"
msgstr "Aktiviert"
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "deactivated"
msgstr "Deaktiviert"
-#: ../../app/controllers/users_controller.rb:156
+#: ../../app/controllers/users_controller.rb:157
msgid "Unable to %{action} %{username}"
msgstr "Kann nicht zu %{action} %{username}"
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "activate"
msgstr "Aktivieren"
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "deactivate"
msgstr "Deaktivieren"
@@ -1286,50 +1294,50 @@ msgstr "Letzte 9 Monate"
msgid "Last 12 months"
msgstr "Letzte 12 Monate"
-#: ../../app/mailers/user_mailer.rb:17
+#: ../../app/mailers/user_mailer.rb:18
#: ../../app/views/devise/mailer/invitation_instructions.html.erb:5
#: ../../app/views/devise/mailer/reset_password_instructions.html.erb:5
#: ../../app/views/user_mailer/_email_signature.html.erb:2
msgid "Query or feedback related to %{tool_name}"
msgstr "Abfrage oder Feedback zu %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:25
+#: ../../app/mailers/user_mailer.rb:26
msgid "Welcome to %{tool_name}"
msgstr "Willkommen bei %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:62
+#: ../../app/mailers/user_mailer.rb:63
msgid "A Data Management Plan in %{tool_name} has been shared with you"
msgstr "Ein Datenverwaltungsplan in %{tool_name} wurde mit Ihnen geteilt"
-#: ../../app/mailers/user_mailer.rb:79
+#: ../../app/mailers/user_mailer.rb:80
msgid "Changed permissions on a Data Management Plan in %{tool_name}"
msgstr "Berechtigungen für einen Datenverwaltungsplan in %{tool_name} geändert"
-#: ../../app/mailers/user_mailer.rb:94
+#: ../../app/mailers/user_mailer.rb:95
msgid "Permissions removed on a DMP in %{tool_name}"
msgstr "Berechtigungen für ein DMP in %{tool_name} entfernt"
-#: ../../app/mailers/user_mailer.rb:112
+#: ../../app/mailers/user_mailer.rb:113
msgid "%{user_name} has requested feedback on a %{tool_name} plan"
msgstr "%{user_name} hat um Feedback zu einem %{tool_name}-Plan gebeten"
-#: ../../app/mailers/user_mailer.rb:135
+#: ../../app/mailers/user_mailer.rb:136
msgid "%{tool_name}: Expert feedback has been provided for %{plan_title}"
msgstr "%{tool_name}: Es wurde Experten-Feedback für %{plan_title} gegeben."
-#: ../../app/mailers/user_mailer.rb:153
+#: ../../app/mailers/user_mailer.rb:154
msgid "DMP Visibility Changed: %{plan_title}"
msgstr "DMP-Sichtbarkeit geändert: %{plan_title}"
-#: ../../app/mailers/user_mailer.rb:182
+#: ../../app/mailers/user_mailer.rb:183
msgid "%{tool_name}: A new comment was added to %{plan_title}"
msgstr "%{tool_name}: Ein neuer Kommentar wurde zu %{plan_title} hinzugefügt."
-#: ../../app/mailers/user_mailer.rb:198
+#: ../../app/mailers/user_mailer.rb:199
msgid "Administrator privileges granted in %{tool_name}"
msgstr "Administratorrechte in erteilt %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:216
+#: ../../app/mailers/user_mailer.rb:217
msgid "%{tool_name} API changes"
msgstr "%{tool_name} API-Änderungen"
@@ -1569,15 +1577,15 @@ msgstr ""
msgid "already assigned a value"
msgstr "bereits einen Wert zugewiesen"
-#: ../../app/models/org.rb:46
+#: ../../app/models/org.rb:47
msgid "Feedback email message"
msgstr "Feedback-Nachricht"
-#: ../../app/models/org.rb:123
+#: ../../app/models/org.rb:124
msgid "must be one of the following formats: jpeg, jpg, png, gif, bmp"
msgstr "muss eines der folgenden Formate sein: jpeg, jpg, png, gif, bmp"
-#: ../../app/models/org.rb:128
+#: ../../app/models/org.rb:129
msgid "can't be larger than 500KB"
msgstr "kann nicht größer als 500KB sein"
@@ -1703,7 +1711,7 @@ msgstr "Sie können keine Vorlage veröffentlichen, die Abschnitte ohne Fragen e
msgid "Conditions in the template refer backwards"
msgstr "Die Bedingungen in der Vorlage beziehen sich rückwärts"
-#: ../../app/models/user.rb:380
+#: ../../app/models/user.rb:386
msgid "A Data Management Plan in %{application_name} has been shared with you"
msgstr "Ein Datenmanagementplan in %{application_name} wurde für Sie freigegeben"
@@ -2133,7 +2141,7 @@ msgstr ""
#: ../../app/views/paginable/templates/_organisational.html.erb:87
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:29
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:36
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
#: ../../app/views/static_pages/about_us.html.erb:22
#: ../../app/views/static_pages/about_us.html.erb:29
#: ../../app/views/static_pages/termsuse.html.erb:46
@@ -4667,7 +4675,7 @@ msgstr "Kommentare & Anleitung"
msgid "Instructions"
msgstr "Anleitung"
-#: ../../app/views/plans/_download_form.html.erb:6
+#: ../../app/views/plans/_download_form.html.erb:5
msgid "Format"
msgstr "Format"
@@ -4675,73 +4683,73 @@ msgstr "Format"
msgid "Download settings"
msgstr "Einstellungen herunterladen"
-#: ../../app/views/plans/_download_form.html.erb:19
-msgid "Select phase to download"
-msgstr "Wählen Sie die Phase zum Herunterladen aus"
-
-#: ../../app/views/plans/_download_form.html.erb:26
+#: ../../app/views/plans/_download_form.html.erb:21
msgid "Optional plan components"
msgstr "Optionale Plankomponenten"
-#: ../../app/views/plans/_download_form.html.erb:30
+#: ../../app/views/plans/_download_form.html.erb:25
msgid "project details coversheet"
msgstr "Deckblatt Projektdetails"
-#: ../../app/views/plans/_download_form.html.erb:36
+#: ../../app/views/plans/_download_form.html.erb:31
msgid "question text and section headings"
msgstr "Fragetext und Abschnittsüberschriften"
-#: ../../app/views/plans/_download_form.html.erb:42
+#: ../../app/views/plans/_download_form.html.erb:37
msgid "unanswered questions"
msgstr "unbeantwortete Fragen"
-#: ../../app/views/plans/_download_form.html.erb:49
+#: ../../app/views/plans/_download_form.html.erb:44
msgid "research outputs"
msgstr "Forschungsergebnisse"
-#: ../../app/views/plans/_download_form.html.erb:57
+#: ../../app/views/plans/_download_form.html.erb:52
msgid "supplementary section(s) not requested by funding organisation"
msgstr ""
"ergänzende(r) Abschnitt(e), die von der Förderorganisation nicht gefordert wer"
"den"
-#: ../../app/views/plans/_download_form.html.erb:65
+#: ../../app/views/plans/_download_form.html.erb:61
+msgid "Select phase to download"
+msgstr "Wählen Sie die Phase zum Herunterladen aus"
+
+#: ../../app/views/plans/_download_form.html.erb:70
msgid "PDF formatting"
msgstr "PDF-Formatierung"
-#: ../../app/views/plans/_download_form.html.erb:68
+#: ../../app/views/plans/_download_form.html.erb:73
msgid "Font"
msgstr "Schrift"
-#: ../../app/views/plans/_download_form.html.erb:71
+#: ../../app/views/plans/_download_form.html.erb:76
msgid "Margin (mm)"
msgstr "Rand (mm)"
-#: ../../app/views/plans/_download_form.html.erb:76
+#: ../../app/views/plans/_download_form.html.erb:81
msgid "Face"
msgstr "Schriftart"
-#: ../../app/views/plans/_download_form.html.erb:84
+#: ../../app/views/plans/_download_form.html.erb:89
msgid "Size"
msgstr "Größe"
-#: ../../app/views/plans/_download_form.html.erb:92
+#: ../../app/views/plans/_download_form.html.erb:96
msgid "Top"
msgstr "Oben"
-#: ../../app/views/plans/_download_form.html.erb:101
+#: ../../app/views/plans/_download_form.html.erb:105
msgid "Bottom"
msgstr "Seitenende"
-#: ../../app/views/plans/_download_form.html.erb:110
+#: ../../app/views/plans/_download_form.html.erb:114
msgid "Left"
msgstr "Links"
-#: ../../app/views/plans/_download_form.html.erb:119
+#: ../../app/views/plans/_download_form.html.erb:123
msgid "Right"
msgstr "Rechts"
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
msgid ""
"Download Plan (new window)%{open_in_new_window_text}"
diff --git a/config/locale/en/LC_MESSAGES/app.mo b/config/locale/en/LC_MESSAGES/app.mo
index 83532d79fa..a5667b9c27 100644
Binary files a/config/locale/en/LC_MESSAGES/app.mo and b/config/locale/en/LC_MESSAGES/app.mo differ
diff --git a/config/locale/en/app.po b/config/locale/en/app.po
index 90661f9691..5833e9b41d 100644
--- a/config/locale/en/app.po
+++ b/config/locale/en/app.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: roadmap_upstream 1.0\n"
"Report-Msgid-Bugs-To: contact@translation.io\n"
-"POT-Creation-Date: 2025-04-10 13:28-0600\n"
-"PO-Revision-Date: 2025-04-10 13:28-0600\n"
+"POT-Creation-Date: 2025-12-23 08:33-0700\n"
+"PO-Revision-Date: 2025-12-23 08:33-0700\n"
"Last-Translator: FULL NAME \n"
"Language-Team: English\n"
"Language: en\n"
@@ -127,87 +127,95 @@ msgstr "Invalid JSON"
msgid "No Plans found"
msgstr "No Plans found"
-#: ../../app/controllers/application_controller.rb:36
+#: ../../app/controllers/api/v2/base_api_controller.rb:72
+msgid "There was a problem in the server."
+msgstr "There was a problem in the server."
+
+#: ../../app/controllers/api/v2/base_api_controller.rb:78
+msgid "The client is not authorized to perform this action."
+msgstr "The client is not authorized to perform this action."
+
+#: ../../app/controllers/application_controller.rb:37
msgid "You are not authorized to perform this action."
msgstr "You are not authorized to perform this action."
-#: ../../app/controllers/application_controller.rb:40
+#: ../../app/controllers/application_controller.rb:41
msgid "You need to sign in or sign up before continuing."
msgstr "You need to sign in or sign up before continuing."
-#: ../../app/controllers/application_controller.rb:108
+#: ../../app/controllers/application_controller.rb:115
msgid "Unable to %{action} the %{object}. %{errors}"
msgstr "Unable to %{action} the %{object}. %{errors}"
-#: ../../app/controllers/application_controller.rb:114
+#: ../../app/controllers/application_controller.rb:121
msgid "Successfully %{action} the %{object}."
msgstr "Successfully %{action} the %{object}."
-#: ../../app/controllers/application_controller.rb:127
+#: ../../app/controllers/application_controller.rb:134
msgid "API client"
msgstr "API client"
-#: ../../app/controllers/application_controller.rb:128
+#: ../../app/controllers/application_controller.rb:135
msgid "plan"
msgstr "plan"
-#: ../../app/controllers/application_controller.rb:129
+#: ../../app/controllers/application_controller.rb:136
msgid "guidance group"
msgstr "guidance group"
-#: ../../app/controllers/application_controller.rb:130
+#: ../../app/controllers/application_controller.rb:137
msgid "comment"
msgstr "comment"
-#: ../../app/controllers/application_controller.rb:131
+#: ../../app/controllers/application_controller.rb:138
msgid "organisation"
msgstr "organisation"
-#: ../../app/controllers/application_controller.rb:132
+#: ../../app/controllers/application_controller.rb:139
msgid "permission"
msgstr "permission"
-#: ../../app/controllers/application_controller.rb:133
+#: ../../app/controllers/application_controller.rb:140
msgid "preferences"
msgstr "preferences"
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "profile"
msgstr "profile"
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "user"
msgstr "user"
-#: ../../app/controllers/application_controller.rb:135
+#: ../../app/controllers/application_controller.rb:142
msgid "question option"
msgstr "question option"
-#: ../../app/controllers/application_controller.rb:181
+#: ../../app/controllers/application_controller.rb:188
msgid "Record Not Found"
msgstr "Record Not Found"
-#: ../../app/controllers/concerns/paginable.rb:45
+#: ../../app/controllers/concerns/paginable.rb:46
msgid "scope should be an ActiveRecord::Relation object"
msgstr "scope should be an ActiveRecord::Relation object"
-#: ../../app/controllers/concerns/paginable.rb:47
+#: ../../app/controllers/concerns/paginable.rb:48
msgid "path_params should be a Hash object"
msgstr "path_params should be a Hash object"
-#: ../../app/controllers/concerns/paginable.rb:48
+#: ../../app/controllers/concerns/paginable.rb:49
msgid "query_params should be a Hash object"
msgstr "query_params should be a Hash object"
-#: ../../app/controllers/concerns/paginable.rb:49
+#: ../../app/controllers/concerns/paginable.rb:50
msgid "locals should be a Hash object"
msgstr "locals should be a Hash object"
-#: ../../app/controllers/concerns/paginable.rb:70
+#: ../../app/controllers/concerns/paginable.rb:71
msgid "Restricted access to View All the records"
msgstr "Restricted access to View All the records"
-#: ../../app/controllers/concerns/paginable.rb:183
+#: ../../app/controllers/concerns/paginable.rb:184
msgid "Sort by %{sort_field}"
msgstr "Sort by %{sort_field}"
@@ -248,77 +256,77 @@ msgstr "Contact email was successfully sent."
msgid "Unable to submit your request"
msgstr "Unable to submit your request"
-#: ../../app/controllers/contributors_controller.rb:40
-#: ../../app/controllers/contributors_controller.rb:56
+#: ../../app/controllers/contributors_controller.rb:41
+#: ../../app/controllers/contributors_controller.rb:57
#: ../../app/controllers/research_outputs_controller.rb:42
msgid "add"
msgstr "add"
-#: ../../app/controllers/contributors_controller.rb:54
+#: ../../app/controllers/contributors_controller.rb:55
#: ../../app/controllers/research_outputs_controller.rb:40
msgid "added"
msgstr "added"
-#: ../../app/controllers/contributors_controller.rb:72
+#: ../../app/controllers/contributors_controller.rb:73
#: ../../app/controllers/guidance_groups_controller.rb:55
#: ../../app/controllers/guidances_controller.rb:75
-#: ../../app/controllers/notes_controller.rb:88
+#: ../../app/controllers/notes_controller.rb:89
#: ../../app/controllers/org_admin/departments_controller.rb:50
#: ../../app/controllers/org_admin/sections_controller.rb:103
#: ../../app/controllers/org_admin/templates_controller.rb:210
#: ../../app/controllers/orgs_controller.rb:92
-#: ../../app/controllers/plans_controller.rb:280
-#: ../../app/controllers/plans_controller.rb:283
+#: ../../app/controllers/plans_controller.rb:281
+#: ../../app/controllers/plans_controller.rb:284
#: ../../app/controllers/registrations_controller.rb:249
#: ../../app/controllers/registrations_controller.rb:253
#: ../../app/controllers/registrations_controller.rb:280
#: ../../app/controllers/registrations_controller.rb:284
#: ../../app/controllers/research_outputs_controller.rb:60
-#: ../../app/controllers/users_controller.rb:103
-#: ../../app/controllers/users_controller.rb:131
+#: ../../app/controllers/users_controller.rb:104
+#: ../../app/controllers/users_controller.rb:132
msgid "saved"
msgstr "saved"
-#: ../../app/controllers/contributors_controller.rb:74
+#: ../../app/controllers/contributors_controller.rb:75
#: ../../app/controllers/guidance_groups_controller.rb:57
#: ../../app/controllers/guidances_controller.rb:77
-#: ../../app/controllers/notes_controller.rb:106
+#: ../../app/controllers/notes_controller.rb:107
#: ../../app/controllers/org_admin/departments_controller.rb:52
#: ../../app/controllers/org_admin/sections_controller.rb:105
#: ../../app/controllers/org_admin/templates_controller.rb:215
#: ../../app/controllers/orgs_controller.rb:94
-#: ../../app/controllers/plans_controller.rb:289
-#: ../../app/controllers/plans_controller.rb:292
-#: ../../app/controllers/plans_controller.rb:296
-#: ../../app/controllers/plans_controller.rb:299
+#: ../../app/controllers/plans_controller.rb:290
+#: ../../app/controllers/plans_controller.rb:293
+#: ../../app/controllers/plans_controller.rb:297
+#: ../../app/controllers/plans_controller.rb:300
#: ../../app/controllers/registrations_controller.rb:256
#: ../../app/controllers/registrations_controller.rb:287
#: ../../app/controllers/research_outputs_controller.rb:63
msgid "save"
msgstr "save"
-#: ../../app/controllers/contributors_controller.rb:83
-#: ../../app/controllers/notes_controller.rb:130
+#: ../../app/controllers/contributors_controller.rb:84
+#: ../../app/controllers/notes_controller.rb:131
#: ../../app/controllers/org_admin/templates_controller.rb:243
#: ../../app/controllers/research_outputs_controller.rb:74
#: ../../app/controllers/super_admin/orgs_controller.rb:94
msgid "removed"
msgstr "removed"
-#: ../../app/controllers/contributors_controller.rb:86
-#: ../../app/controllers/notes_controller.rb:148
+#: ../../app/controllers/contributors_controller.rb:87
+#: ../../app/controllers/notes_controller.rb:149
#: ../../app/controllers/org_admin/templates_controller.rb:245
#: ../../app/controllers/research_outputs_controller.rb:77
#: ../../app/controllers/super_admin/orgs_controller.rb:97
msgid "remove"
msgstr "remove"
-#: ../../app/controllers/contributors_controller.rb:160
+#: ../../app/controllers/contributors_controller.rb:161
#: ../../app/controllers/research_outputs_controller.rb:208
msgid "plan not found"
msgstr "plan not found"
-#: ../../app/controllers/contributors_controller.rb:168
+#: ../../app/controllers/contributors_controller.rb:169
msgid "contributor not found"
msgstr "contributor not found"
@@ -332,7 +340,7 @@ msgstr "An error occurred when requesting feedback for this plan."
#: ../../app/controllers/guidance_groups_controller.rb:31
#: ../../app/controllers/guidances_controller.rb:53
-#: ../../app/controllers/notes_controller.rb:47
+#: ../../app/controllers/notes_controller.rb:48
#: ../../app/controllers/org_admin/departments_controller.rb:26
#: ../../app/controllers/org_admin/phases_controller.rb:121
#: ../../app/controllers/org_admin/questions_controller.rb:94
@@ -348,7 +356,7 @@ msgstr "created"
#: ../../app/controllers/guidance_groups_controller.rb:34
#: ../../app/controllers/guidances_controller.rb:55
-#: ../../app/controllers/notes_controller.rb:66
+#: ../../app/controllers/notes_controller.rb:67
#: ../../app/controllers/org_admin/departments_controller.rb:30
#: ../../app/controllers/org_admin/phases_controller.rb:123
#: ../../app/controllers/org_admin/questions_controller.rb:96
@@ -387,7 +395,7 @@ msgstr "unpublish"
#: ../../app/controllers/org_admin/question_options_controller.rb:24
#: ../../app/controllers/org_admin/questions_controller.rb:197
#: ../../app/controllers/org_admin/sections_controller.rb:128
-#: ../../app/controllers/plans_controller.rb:342
+#: ../../app/controllers/plans_controller.rb:343
#: ../../app/controllers/super_admin/api_clients_controller.rb:81
#: ../../app/controllers/super_admin/notifications_controller.rb:85
#: ../../app/controllers/super_admin/themes_controller.rb:51
@@ -401,7 +409,7 @@ msgstr "deleted"
#: ../../app/controllers/org_admin/question_options_controller.rb:26
#: ../../app/controllers/org_admin/questions_controller.rb:199
#: ../../app/controllers/org_admin/sections_controller.rb:130
-#: ../../app/controllers/plans_controller.rb:347
+#: ../../app/controllers/plans_controller.rb:348
#: ../../app/controllers/super_admin/api_clients_controller.rb:84
#: ../../app/controllers/super_admin/notifications_controller.rb:88
#: ../../app/controllers/super_admin/themes_controller.rb:54
@@ -444,19 +452,19 @@ msgstr "Unable to create a new version of this template.
"
#: ../../app/controllers/org_admin/phases_controller.rb:147
#: ../../app/controllers/org_admin/questions_controller.rb:166
#: ../../app/controllers/org_admin/users_controller.rb:30
-#: ../../app/controllers/plans_controller.rb:416
+#: ../../app/controllers/plans_controller.rb:417
#: ../../app/controllers/super_admin/api_clients_controller.rb:68
#: ../../app/controllers/super_admin/notifications_controller.rb:52
#: ../../app/controllers/super_admin/themes_controller.rb:39
#: ../../app/controllers/super_admin/users_controller.rb:54
-#: ../../app/controllers/users_controller.rb:108
+#: ../../app/controllers/users_controller.rb:109
msgid "updated"
msgstr "updated"
#: ../../app/controllers/org_admin/phases_controller.rb:149
#: ../../app/controllers/org_admin/questions_controller.rb:169
#: ../../app/controllers/org_admin/users_controller.rb:32
-#: ../../app/controllers/plans_controller.rb:419
+#: ../../app/controllers/plans_controller.rb:420
#: ../../app/controllers/super_admin/api_clients_controller.rb:70
#: ../../app/controllers/super_admin/notifications_controller.rb:55
#: ../../app/controllers/super_admin/themes_controller.rb:41
@@ -546,7 +554,7 @@ msgid "Unable to delete this version of the template."
msgstr "Unable to delete this version of the template."
#: ../../app/controllers/org_admin/template_copies_controller.rb:20
-#: ../../app/controllers/plans_controller.rb:395
+#: ../../app/controllers/plans_controller.rb:396
msgid "copy"
msgstr "copy"
@@ -555,11 +563,11 @@ msgstr "copy"
msgid "That template is no longer customizable."
msgstr "That template is no longer customizable."
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:21
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:22
msgid "Unable to customize that template."
msgstr "Unable to customize that template."
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:24
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:25
msgid "That template is not customizable."
msgstr "That template is not customizable."
@@ -649,11 +657,11 @@ msgstr "This plan is based on the"
msgid "template with customisations by the"
msgstr "template with customisations by the"
-#: ../../app/controllers/plans_controller.rb:393
+#: ../../app/controllers/plans_controller.rb:394
msgid "copied"
msgstr "copied"
-#: ../../app/controllers/plans_controller.rb:424
+#: ../../app/controllers/plans_controller.rb:425
msgid ""
"Unable to change the plan's status since it is needed at least %{percentage} p"
"ercentage responded"
@@ -661,23 +669,23 @@ msgstr ""
"Unable to change the plan's status since it is needed at least %{percentage} p"
"ercentage responded"
-#: ../../app/controllers/plans_controller.rb:430
+#: ../../app/controllers/plans_controller.rb:431
msgid "Unable to find plan id %{plan_id}"
msgstr "Unable to find plan id %{plan_id}"
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is now a test."
msgstr "Your project is now a test."
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is no longer a test."
msgstr "Your project is no longer a test."
-#: ../../app/controllers/plans_controller.rb:449
+#: ../../app/controllers/plans_controller.rb:450
msgid "Unable to change the plan's test status"
msgstr "Unable to change the plan's test status"
-#: ../../app/controllers/plans_controller.rb:462
+#: ../../app/controllers/plans_controller.rb:463
msgid "There is no plan associated with id %{s"
msgstr "There is no plan associated with id %{s"
@@ -775,7 +783,7 @@ msgstr "Password and comfirmation must match"
msgid "research output not found"
msgstr "research output not found"
-#: ../../app/controllers/roles_controller.rb:26
+#: ../../app/controllers/roles_controller.rb:27
msgid ""
"Cannot share plan with %{email} since that email matches\n"
" with the owner of the plan."
@@ -952,27 +960,27 @@ msgstr "Your account has been successfully linked to %{scheme}."
msgid "Unable to link your account to %{scheme}."
msgstr "Unable to link your account to %{scheme}."
-#: ../../app/controllers/users_controller.rb:149
+#: ../../app/controllers/users_controller.rb:150
msgid "Successfully %{action} %{username}'s account."
msgstr "Successfully %{action} %{username}'s account."
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "activated"
msgstr "activated"
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "deactivated"
msgstr "deactivated"
-#: ../../app/controllers/users_controller.rb:156
+#: ../../app/controllers/users_controller.rb:157
msgid "Unable to %{action} %{username}"
msgstr "Unable to %{action} %{username}"
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "activate"
msgstr "activate"
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "deactivate"
msgstr "deactivate"
@@ -1266,50 +1274,50 @@ msgstr "Last 9 months"
msgid "Last 12 months"
msgstr "Last 12 months"
-#: ../../app/mailers/user_mailer.rb:17
+#: ../../app/mailers/user_mailer.rb:18
#: ../../app/views/devise/mailer/invitation_instructions.html.erb:5
#: ../../app/views/devise/mailer/reset_password_instructions.html.erb:5
#: ../../app/views/user_mailer/_email_signature.html.erb:2
msgid "Query or feedback related to %{tool_name}"
msgstr "Query or feedback related to %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:25
+#: ../../app/mailers/user_mailer.rb:26
msgid "Welcome to %{tool_name}"
msgstr "Welcome to %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:62
+#: ../../app/mailers/user_mailer.rb:63
msgid "A Data Management Plan in %{tool_name} has been shared with you"
msgstr "A Data Management Plan in %{tool_name} has been shared with you"
-#: ../../app/mailers/user_mailer.rb:79
+#: ../../app/mailers/user_mailer.rb:80
msgid "Changed permissions on a Data Management Plan in %{tool_name}"
msgstr "Changed permissions on a Data Management Plan in %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:94
+#: ../../app/mailers/user_mailer.rb:95
msgid "Permissions removed on a DMP in %{tool_name}"
msgstr "Permissions removed on a DMP in %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:112
+#: ../../app/mailers/user_mailer.rb:113
msgid "%{user_name} has requested feedback on a %{tool_name} plan"
msgstr "%{user_name} has requested feedback on a %{tool_name} plan"
-#: ../../app/mailers/user_mailer.rb:135
+#: ../../app/mailers/user_mailer.rb:136
msgid "%{tool_name}: Expert feedback has been provided for %{plan_title}"
msgstr "%{tool_name}: Expert feedback has been provided for %{plan_title}"
-#: ../../app/mailers/user_mailer.rb:153
+#: ../../app/mailers/user_mailer.rb:154
msgid "DMP Visibility Changed: %{plan_title}"
msgstr "DMP Visibility Changed: %{plan_title}"
-#: ../../app/mailers/user_mailer.rb:182
+#: ../../app/mailers/user_mailer.rb:183
msgid "%{tool_name}: A new comment was added to %{plan_title}"
msgstr "%{tool_name}: A new comment was added to %{plan_title}"
-#: ../../app/mailers/user_mailer.rb:198
+#: ../../app/mailers/user_mailer.rb:199
msgid "Administrator privileges granted in %{tool_name}"
msgstr "Administrator privileges granted in %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:216
+#: ../../app/mailers/user_mailer.rb:217
msgid "%{tool_name} API changes"
msgstr "%{tool_name} API changes"
@@ -1549,15 +1557,15 @@ msgstr "Question not answered.\\n"
msgid "already assigned a value"
msgstr "already assigned a value"
-#: ../../app/models/org.rb:46
+#: ../../app/models/org.rb:47
msgid "Feedback email message"
msgstr "Feedback email message"
-#: ../../app/models/org.rb:123
+#: ../../app/models/org.rb:124
msgid "must be one of the following formats: jpeg, jpg, png, gif, bmp"
msgstr "must be one of the following formats: jpeg, jpg, png, gif, bmp"
-#: ../../app/models/org.rb:128
+#: ../../app/models/org.rb:129
msgid "can't be larger than 500KB"
msgstr "can't be larger than 500KB"
@@ -1681,7 +1689,7 @@ msgstr "You can not publish a template without questions in a section. "
msgid "Conditions in the template refer backwards"
msgstr "Conditions in the template refer backwards"
-#: ../../app/models/user.rb:380
+#: ../../app/models/user.rb:386
msgid "A Data Management Plan in %{application_name} has been shared with you"
msgstr "A Data Management Plan in %{application_name} has been shared with you"
@@ -2114,7 +2122,7 @@ msgstr ""
#: ../../app/views/paginable/templates/_organisational.html.erb:87
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:29
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:36
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
#: ../../app/views/static_pages/about_us.html.erb:22
#: ../../app/views/static_pages/about_us.html.erb:29
#: ../../app/views/static_pages/termsuse.html.erb:46
@@ -4612,7 +4620,7 @@ msgstr "Comments & Guidance"
msgid "Instructions"
msgstr "Instructions"
-#: ../../app/views/plans/_download_form.html.erb:6
+#: ../../app/views/plans/_download_form.html.erb:5
msgid "Format"
msgstr "Format"
@@ -4620,71 +4628,71 @@ msgstr "Format"
msgid "Download settings"
msgstr "Download settings"
-#: ../../app/views/plans/_download_form.html.erb:19
-msgid "Select phase to download"
-msgstr "Select phase to download"
-
-#: ../../app/views/plans/_download_form.html.erb:26
+#: ../../app/views/plans/_download_form.html.erb:21
msgid "Optional plan components"
msgstr "Optional plan components"
-#: ../../app/views/plans/_download_form.html.erb:30
+#: ../../app/views/plans/_download_form.html.erb:25
msgid "project details coversheet"
msgstr "project details coversheet"
-#: ../../app/views/plans/_download_form.html.erb:36
+#: ../../app/views/plans/_download_form.html.erb:31
msgid "question text and section headings"
msgstr "question text and section headings"
-#: ../../app/views/plans/_download_form.html.erb:42
+#: ../../app/views/plans/_download_form.html.erb:37
msgid "unanswered questions"
msgstr "unanswered questions"
-#: ../../app/views/plans/_download_form.html.erb:49
+#: ../../app/views/plans/_download_form.html.erb:44
msgid "research outputs"
msgstr "research outputs"
-#: ../../app/views/plans/_download_form.html.erb:57
+#: ../../app/views/plans/_download_form.html.erb:52
msgid "supplementary section(s) not requested by funding organisation"
msgstr "supplementary section(s) not requested by funding organisation"
-#: ../../app/views/plans/_download_form.html.erb:65
+#: ../../app/views/plans/_download_form.html.erb:61
+msgid "Select phase to download"
+msgstr "Select phase to download"
+
+#: ../../app/views/plans/_download_form.html.erb:70
msgid "PDF formatting"
msgstr "PDF formatting"
-#: ../../app/views/plans/_download_form.html.erb:68
+#: ../../app/views/plans/_download_form.html.erb:73
msgid "Font"
msgstr "Font"
-#: ../../app/views/plans/_download_form.html.erb:71
+#: ../../app/views/plans/_download_form.html.erb:76
msgid "Margin (mm)"
msgstr "Margin (mm)"
-#: ../../app/views/plans/_download_form.html.erb:76
+#: ../../app/views/plans/_download_form.html.erb:81
msgid "Face"
msgstr "Face"
-#: ../../app/views/plans/_download_form.html.erb:84
+#: ../../app/views/plans/_download_form.html.erb:89
msgid "Size"
msgstr "Size"
-#: ../../app/views/plans/_download_form.html.erb:92
+#: ../../app/views/plans/_download_form.html.erb:96
msgid "Top"
msgstr "Top"
-#: ../../app/views/plans/_download_form.html.erb:101
+#: ../../app/views/plans/_download_form.html.erb:105
msgid "Bottom"
msgstr "Bottom"
-#: ../../app/views/plans/_download_form.html.erb:110
+#: ../../app/views/plans/_download_form.html.erb:114
msgid "Left"
msgstr "Left"
-#: ../../app/views/plans/_download_form.html.erb:119
+#: ../../app/views/plans/_download_form.html.erb:123
msgid "Right"
msgstr "Right"
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
msgid ""
"Download Plan (new window)%{open_in_new_window_text}"
diff --git a/config/locale/en_CA/LC_MESSAGES/app.mo b/config/locale/en_CA/LC_MESSAGES/app.mo
index bf9d6b2adf..aa7816ac0c 100644
Binary files a/config/locale/en_CA/LC_MESSAGES/app.mo and b/config/locale/en_CA/LC_MESSAGES/app.mo differ
diff --git a/config/locale/en_CA/app.po b/config/locale/en_CA/app.po
index 8ab07d0dae..9481090fbb 100644
--- a/config/locale/en_CA/app.po
+++ b/config/locale/en_CA/app.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: roadmap_upstream 1.0\n"
"Report-Msgid-Bugs-To: contact@translation.io\n"
-"POT-Creation-Date: 2025-04-10 13:28-0600\n"
-"PO-Revision-Date: 2025-04-10 21:28+0200\n"
+"POT-Creation-Date: 2025-12-23 08:33-0700\n"
+"PO-Revision-Date: 2025-12-23 15:33+0000\n"
"Last-Translator: FULL NAME \n"
"Language-Team: English\n"
"Language: en_CA\n"
@@ -123,87 +123,95 @@ msgstr ""
msgid "No Plans found"
msgstr ""
-#: ../../app/controllers/application_controller.rb:36
+#: ../../app/controllers/api/v2/base_api_controller.rb:72
+msgid "There was a problem in the server."
+msgstr ""
+
+#: ../../app/controllers/api/v2/base_api_controller.rb:78
+msgid "The client is not authorized to perform this action."
+msgstr ""
+
+#: ../../app/controllers/application_controller.rb:37
msgid "You are not authorized to perform this action."
msgstr ""
-#: ../../app/controllers/application_controller.rb:40
+#: ../../app/controllers/application_controller.rb:41
msgid "You need to sign in or sign up before continuing."
msgstr "You need to sign in or sign up before continuing."
-#: ../../app/controllers/application_controller.rb:108
+#: ../../app/controllers/application_controller.rb:115
msgid "Unable to %{action} the %{object}. %{errors}"
msgstr ""
-#: ../../app/controllers/application_controller.rb:114
+#: ../../app/controllers/application_controller.rb:121
msgid "Successfully %{action} the %{object}."
msgstr ""
-#: ../../app/controllers/application_controller.rb:127
+#: ../../app/controllers/application_controller.rb:134
msgid "API client"
msgstr ""
-#: ../../app/controllers/application_controller.rb:128
+#: ../../app/controllers/application_controller.rb:135
msgid "plan"
msgstr ""
-#: ../../app/controllers/application_controller.rb:129
+#: ../../app/controllers/application_controller.rb:136
msgid "guidance group"
msgstr ""
-#: ../../app/controllers/application_controller.rb:130
+#: ../../app/controllers/application_controller.rb:137
msgid "comment"
msgstr ""
-#: ../../app/controllers/application_controller.rb:131
+#: ../../app/controllers/application_controller.rb:138
msgid "organisation"
msgstr ""
-#: ../../app/controllers/application_controller.rb:132
+#: ../../app/controllers/application_controller.rb:139
msgid "permission"
msgstr ""
-#: ../../app/controllers/application_controller.rb:133
+#: ../../app/controllers/application_controller.rb:140
msgid "preferences"
msgstr ""
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "profile"
msgstr ""
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "user"
msgstr ""
-#: ../../app/controllers/application_controller.rb:135
+#: ../../app/controllers/application_controller.rb:142
msgid "question option"
msgstr ""
-#: ../../app/controllers/application_controller.rb:181
+#: ../../app/controllers/application_controller.rb:188
msgid "Record Not Found"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:45
+#: ../../app/controllers/concerns/paginable.rb:46
msgid "scope should be an ActiveRecord::Relation object"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:47
+#: ../../app/controllers/concerns/paginable.rb:48
msgid "path_params should be a Hash object"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:48
+#: ../../app/controllers/concerns/paginable.rb:49
msgid "query_params should be a Hash object"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:49
+#: ../../app/controllers/concerns/paginable.rb:50
msgid "locals should be a Hash object"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:70
+#: ../../app/controllers/concerns/paginable.rb:71
msgid "Restricted access to View All the records"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:183
+#: ../../app/controllers/concerns/paginable.rb:184
msgid "Sort by %{sort_field}"
msgstr ""
@@ -244,77 +252,77 @@ msgstr ""
msgid "Unable to submit your request"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:40
-#: ../../app/controllers/contributors_controller.rb:56
+#: ../../app/controllers/contributors_controller.rb:41
+#: ../../app/controllers/contributors_controller.rb:57
#: ../../app/controllers/research_outputs_controller.rb:42
msgid "add"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:54
+#: ../../app/controllers/contributors_controller.rb:55
#: ../../app/controllers/research_outputs_controller.rb:40
msgid "added"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:72
+#: ../../app/controllers/contributors_controller.rb:73
#: ../../app/controllers/guidance_groups_controller.rb:55
#: ../../app/controllers/guidances_controller.rb:75
-#: ../../app/controllers/notes_controller.rb:88
+#: ../../app/controllers/notes_controller.rb:89
#: ../../app/controllers/org_admin/departments_controller.rb:50
#: ../../app/controllers/org_admin/sections_controller.rb:103
#: ../../app/controllers/org_admin/templates_controller.rb:210
#: ../../app/controllers/orgs_controller.rb:92
-#: ../../app/controllers/plans_controller.rb:280
-#: ../../app/controllers/plans_controller.rb:283
+#: ../../app/controllers/plans_controller.rb:281
+#: ../../app/controllers/plans_controller.rb:284
#: ../../app/controllers/registrations_controller.rb:249
#: ../../app/controllers/registrations_controller.rb:253
#: ../../app/controllers/registrations_controller.rb:280
#: ../../app/controllers/registrations_controller.rb:284
#: ../../app/controllers/research_outputs_controller.rb:60
-#: ../../app/controllers/users_controller.rb:103
-#: ../../app/controllers/users_controller.rb:131
+#: ../../app/controllers/users_controller.rb:104
+#: ../../app/controllers/users_controller.rb:132
msgid "saved"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:74
+#: ../../app/controllers/contributors_controller.rb:75
#: ../../app/controllers/guidance_groups_controller.rb:57
#: ../../app/controllers/guidances_controller.rb:77
-#: ../../app/controllers/notes_controller.rb:106
+#: ../../app/controllers/notes_controller.rb:107
#: ../../app/controllers/org_admin/departments_controller.rb:52
#: ../../app/controllers/org_admin/sections_controller.rb:105
#: ../../app/controllers/org_admin/templates_controller.rb:215
#: ../../app/controllers/orgs_controller.rb:94
-#: ../../app/controllers/plans_controller.rb:289
-#: ../../app/controllers/plans_controller.rb:292
-#: ../../app/controllers/plans_controller.rb:296
-#: ../../app/controllers/plans_controller.rb:299
+#: ../../app/controllers/plans_controller.rb:290
+#: ../../app/controllers/plans_controller.rb:293
+#: ../../app/controllers/plans_controller.rb:297
+#: ../../app/controllers/plans_controller.rb:300
#: ../../app/controllers/registrations_controller.rb:256
#: ../../app/controllers/registrations_controller.rb:287
#: ../../app/controllers/research_outputs_controller.rb:63
msgid "save"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:83
-#: ../../app/controllers/notes_controller.rb:130
+#: ../../app/controllers/contributors_controller.rb:84
+#: ../../app/controllers/notes_controller.rb:131
#: ../../app/controllers/org_admin/templates_controller.rb:243
#: ../../app/controllers/research_outputs_controller.rb:74
#: ../../app/controllers/super_admin/orgs_controller.rb:94
msgid "removed"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:86
-#: ../../app/controllers/notes_controller.rb:148
+#: ../../app/controllers/contributors_controller.rb:87
+#: ../../app/controllers/notes_controller.rb:149
#: ../../app/controllers/org_admin/templates_controller.rb:245
#: ../../app/controllers/research_outputs_controller.rb:77
#: ../../app/controllers/super_admin/orgs_controller.rb:97
msgid "remove"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:160
+#: ../../app/controllers/contributors_controller.rb:161
#: ../../app/controllers/research_outputs_controller.rb:208
msgid "plan not found"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:168
+#: ../../app/controllers/contributors_controller.rb:169
msgid "contributor not found"
msgstr ""
@@ -328,7 +336,7 @@ msgstr ""
#: ../../app/controllers/guidance_groups_controller.rb:31
#: ../../app/controllers/guidances_controller.rb:53
-#: ../../app/controllers/notes_controller.rb:47
+#: ../../app/controllers/notes_controller.rb:48
#: ../../app/controllers/org_admin/departments_controller.rb:26
#: ../../app/controllers/org_admin/phases_controller.rb:121
#: ../../app/controllers/org_admin/questions_controller.rb:94
@@ -344,7 +352,7 @@ msgstr ""
#: ../../app/controllers/guidance_groups_controller.rb:34
#: ../../app/controllers/guidances_controller.rb:55
-#: ../../app/controllers/notes_controller.rb:66
+#: ../../app/controllers/notes_controller.rb:67
#: ../../app/controllers/org_admin/departments_controller.rb:30
#: ../../app/controllers/org_admin/phases_controller.rb:123
#: ../../app/controllers/org_admin/questions_controller.rb:96
@@ -383,7 +391,7 @@ msgstr ""
#: ../../app/controllers/org_admin/question_options_controller.rb:24
#: ../../app/controllers/org_admin/questions_controller.rb:197
#: ../../app/controllers/org_admin/sections_controller.rb:128
-#: ../../app/controllers/plans_controller.rb:342
+#: ../../app/controllers/plans_controller.rb:343
#: ../../app/controllers/super_admin/api_clients_controller.rb:81
#: ../../app/controllers/super_admin/notifications_controller.rb:85
#: ../../app/controllers/super_admin/themes_controller.rb:51
@@ -397,7 +405,7 @@ msgstr ""
#: ../../app/controllers/org_admin/question_options_controller.rb:26
#: ../../app/controllers/org_admin/questions_controller.rb:199
#: ../../app/controllers/org_admin/sections_controller.rb:130
-#: ../../app/controllers/plans_controller.rb:347
+#: ../../app/controllers/plans_controller.rb:348
#: ../../app/controllers/super_admin/api_clients_controller.rb:84
#: ../../app/controllers/super_admin/notifications_controller.rb:88
#: ../../app/controllers/super_admin/themes_controller.rb:54
@@ -438,19 +446,19 @@ msgstr ""
#: ../../app/controllers/org_admin/phases_controller.rb:147
#: ../../app/controllers/org_admin/questions_controller.rb:166
#: ../../app/controllers/org_admin/users_controller.rb:30
-#: ../../app/controllers/plans_controller.rb:416
+#: ../../app/controllers/plans_controller.rb:417
#: ../../app/controllers/super_admin/api_clients_controller.rb:68
#: ../../app/controllers/super_admin/notifications_controller.rb:52
#: ../../app/controllers/super_admin/themes_controller.rb:39
#: ../../app/controllers/super_admin/users_controller.rb:54
-#: ../../app/controllers/users_controller.rb:108
+#: ../../app/controllers/users_controller.rb:109
msgid "updated"
msgstr ""
#: ../../app/controllers/org_admin/phases_controller.rb:149
#: ../../app/controllers/org_admin/questions_controller.rb:169
#: ../../app/controllers/org_admin/users_controller.rb:32
-#: ../../app/controllers/plans_controller.rb:419
+#: ../../app/controllers/plans_controller.rb:420
#: ../../app/controllers/super_admin/api_clients_controller.rb:70
#: ../../app/controllers/super_admin/notifications_controller.rb:55
#: ../../app/controllers/super_admin/themes_controller.rb:41
@@ -540,7 +548,7 @@ msgid "Unable to delete this version of the template."
msgstr ""
#: ../../app/controllers/org_admin/template_copies_controller.rb:20
-#: ../../app/controllers/plans_controller.rb:395
+#: ../../app/controllers/plans_controller.rb:396
msgid "copy"
msgstr ""
@@ -549,11 +557,11 @@ msgstr ""
msgid "That template is no longer customizable."
msgstr ""
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:21
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:22
msgid "Unable to customize that template."
msgstr ""
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:24
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:25
msgid "That template is not customizable."
msgstr ""
@@ -643,33 +651,33 @@ msgstr ""
msgid "template with customisations by the"
msgstr ""
-#: ../../app/controllers/plans_controller.rb:393
+#: ../../app/controllers/plans_controller.rb:394
msgid "copied"
msgstr ""
-#: ../../app/controllers/plans_controller.rb:424
+#: ../../app/controllers/plans_controller.rb:425
msgid ""
"Unable to change the plan's status since it is needed at least %{percentage} p"
"ercentage responded"
msgstr ""
-#: ../../app/controllers/plans_controller.rb:430
+#: ../../app/controllers/plans_controller.rb:431
msgid "Unable to find plan id %{plan_id}"
msgstr ""
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is now a test."
msgstr ""
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is no longer a test."
msgstr ""
-#: ../../app/controllers/plans_controller.rb:449
+#: ../../app/controllers/plans_controller.rb:450
msgid "Unable to change the plan's test status"
msgstr ""
-#: ../../app/controllers/plans_controller.rb:462
+#: ../../app/controllers/plans_controller.rb:463
msgid "There is no plan associated with id %{s"
msgstr ""
@@ -754,7 +762,7 @@ msgstr ""
msgid "research output not found"
msgstr ""
-#: ../../app/controllers/roles_controller.rb:26
+#: ../../app/controllers/roles_controller.rb:27
msgid ""
"Cannot share plan with %{email} since that email matches\n"
" with the owner of the plan."
@@ -917,27 +925,27 @@ msgstr ""
msgid "Unable to link your account to %{scheme}."
msgstr ""
-#: ../../app/controllers/users_controller.rb:149
+#: ../../app/controllers/users_controller.rb:150
msgid "Successfully %{action} %{username}'s account."
msgstr ""
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "activated"
msgstr ""
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "deactivated"
msgstr ""
-#: ../../app/controllers/users_controller.rb:156
+#: ../../app/controllers/users_controller.rb:157
msgid "Unable to %{action} %{username}"
msgstr ""
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "activate"
msgstr ""
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "deactivate"
msgstr ""
@@ -1217,50 +1225,50 @@ msgstr ""
msgid "Last 12 months"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:17
+#: ../../app/mailers/user_mailer.rb:18
#: ../../app/views/devise/mailer/invitation_instructions.html.erb:5
#: ../../app/views/devise/mailer/reset_password_instructions.html.erb:5
#: ../../app/views/user_mailer/_email_signature.html.erb:2
msgid "Query or feedback related to %{tool_name}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:25
+#: ../../app/mailers/user_mailer.rb:26
msgid "Welcome to %{tool_name}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:62
+#: ../../app/mailers/user_mailer.rb:63
msgid "A Data Management Plan in %{tool_name} has been shared with you"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:79
+#: ../../app/mailers/user_mailer.rb:80
msgid "Changed permissions on a Data Management Plan in %{tool_name}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:94
+#: ../../app/mailers/user_mailer.rb:95
msgid "Permissions removed on a DMP in %{tool_name}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:112
+#: ../../app/mailers/user_mailer.rb:113
msgid "%{user_name} has requested feedback on a %{tool_name} plan"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:135
+#: ../../app/mailers/user_mailer.rb:136
msgid "%{tool_name}: Expert feedback has been provided for %{plan_title}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:153
+#: ../../app/mailers/user_mailer.rb:154
msgid "DMP Visibility Changed: %{plan_title}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:182
+#: ../../app/mailers/user_mailer.rb:183
msgid "%{tool_name}: A new comment was added to %{plan_title}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:198
+#: ../../app/mailers/user_mailer.rb:199
msgid "Administrator privileges granted in %{tool_name}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:216
+#: ../../app/mailers/user_mailer.rb:217
msgid "%{tool_name} API changes"
msgstr ""
@@ -1490,15 +1498,15 @@ msgstr ""
msgid "already assigned a value"
msgstr ""
-#: ../../app/models/org.rb:46
+#: ../../app/models/org.rb:47
msgid "Feedback email message"
msgstr ""
-#: ../../app/models/org.rb:123
+#: ../../app/models/org.rb:124
msgid "must be one of the following formats: jpeg, jpg, png, gif, bmp"
msgstr ""
-#: ../../app/models/org.rb:128
+#: ../../app/models/org.rb:129
msgid "can't be larger than 500KB"
msgstr ""
@@ -1622,7 +1630,7 @@ msgstr ""
msgid "Conditions in the template refer backwards"
msgstr ""
-#: ../../app/models/user.rb:380
+#: ../../app/models/user.rb:386
msgid "A Data Management Plan in %{application_name} has been shared with you"
msgstr ""
@@ -2032,7 +2040,7 @@ msgstr ""
#: ../../app/views/paginable/templates/_organisational.html.erb:87
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:29
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:36
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
#: ../../app/views/static_pages/about_us.html.erb:22
#: ../../app/views/static_pages/about_us.html.erb:29
#: ../../app/views/static_pages/termsuse.html.erb:46
@@ -4351,7 +4359,7 @@ msgstr ""
msgid "Instructions"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:6
+#: ../../app/views/plans/_download_form.html.erb:5
msgid "Format"
msgstr ""
@@ -4359,71 +4367,71 @@ msgstr ""
msgid "Download settings"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:19
-msgid "Select phase to download"
-msgstr ""
-
-#: ../../app/views/plans/_download_form.html.erb:26
+#: ../../app/views/plans/_download_form.html.erb:21
msgid "Optional plan components"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:30
+#: ../../app/views/plans/_download_form.html.erb:25
msgid "project details coversheet"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:36
+#: ../../app/views/plans/_download_form.html.erb:31
msgid "question text and section headings"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:42
+#: ../../app/views/plans/_download_form.html.erb:37
msgid "unanswered questions"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:49
+#: ../../app/views/plans/_download_form.html.erb:44
msgid "research outputs"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:57
+#: ../../app/views/plans/_download_form.html.erb:52
msgid "supplementary section(s) not requested by funding organisation"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:65
+#: ../../app/views/plans/_download_form.html.erb:61
+msgid "Select phase to download"
+msgstr ""
+
+#: ../../app/views/plans/_download_form.html.erb:70
msgid "PDF formatting"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:68
+#: ../../app/views/plans/_download_form.html.erb:73
msgid "Font"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:71
+#: ../../app/views/plans/_download_form.html.erb:76
msgid "Margin (mm)"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:76
+#: ../../app/views/plans/_download_form.html.erb:81
msgid "Face"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:84
+#: ../../app/views/plans/_download_form.html.erb:89
msgid "Size"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:92
+#: ../../app/views/plans/_download_form.html.erb:96
msgid "Top"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:101
+#: ../../app/views/plans/_download_form.html.erb:105
msgid "Bottom"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:110
+#: ../../app/views/plans/_download_form.html.erb:114
msgid "Left"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:119
+#: ../../app/views/plans/_download_form.html.erb:123
msgid "Right"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
msgid ""
"Download Plan (new window)%{open_in_new_window_text}"
@@ -4965,15 +4973,15 @@ msgstr ""
#: ../../app/views/research_outputs/repositories/_search.html.erb:6
msgid "Select a subject area to refine your search."
-msgstr ""
+msgstr "Select a subject area to refine your search."
#: ../../app/views/research_outputs/repositories/_search.html.erb:12
msgid "- Select a subject area -"
-msgstr ""
+msgstr "- Select a subject area -"
#: ../../app/views/research_outputs/repositories/_search.html.erb:14
msgid "Select a subject area"
-msgstr ""
+msgstr "Select a subject area"
#: ../../app/views/research_outputs/repositories/_search.html.erb:22
msgid "- Select a repository type -"
diff --git a/config/locale/en_GB/LC_MESSAGES/app.mo b/config/locale/en_GB/LC_MESSAGES/app.mo
index eca3c2e99f..21dda0e166 100644
Binary files a/config/locale/en_GB/LC_MESSAGES/app.mo and b/config/locale/en_GB/LC_MESSAGES/app.mo differ
diff --git a/config/locale/en_GB/app.po b/config/locale/en_GB/app.po
index 7479db1f41..465f877b67 100644
--- a/config/locale/en_GB/app.po
+++ b/config/locale/en_GB/app.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: roadmap_upstream 1.0\n"
"Report-Msgid-Bugs-To: contact@translation.io\n"
-"POT-Creation-Date: 2025-04-10 13:28-0600\n"
-"PO-Revision-Date: 2025-04-10 21:28+0200\n"
+"POT-Creation-Date: 2025-12-23 08:33-0700\n"
+"PO-Revision-Date: 2025-12-23 15:33+0000\n"
"Last-Translator: FULL NAME \n"
"Language-Team: English\n"
"Language: en_GB\n"
@@ -123,87 +123,95 @@ msgstr ""
msgid "No Plans found"
msgstr ""
-#: ../../app/controllers/application_controller.rb:36
+#: ../../app/controllers/api/v2/base_api_controller.rb:72
+msgid "There was a problem in the server."
+msgstr ""
+
+#: ../../app/controllers/api/v2/base_api_controller.rb:78
+msgid "The client is not authorized to perform this action."
+msgstr ""
+
+#: ../../app/controllers/application_controller.rb:37
msgid "You are not authorized to perform this action."
msgstr ""
-#: ../../app/controllers/application_controller.rb:40
+#: ../../app/controllers/application_controller.rb:41
msgid "You need to sign in or sign up before continuing."
msgstr "You need to sign in or sign up before continuing."
-#: ../../app/controllers/application_controller.rb:108
+#: ../../app/controllers/application_controller.rb:115
msgid "Unable to %{action} the %{object}. %{errors}"
msgstr ""
-#: ../../app/controllers/application_controller.rb:114
+#: ../../app/controllers/application_controller.rb:121
msgid "Successfully %{action} the %{object}."
msgstr ""
-#: ../../app/controllers/application_controller.rb:127
+#: ../../app/controllers/application_controller.rb:134
msgid "API client"
msgstr ""
-#: ../../app/controllers/application_controller.rb:128
+#: ../../app/controllers/application_controller.rb:135
msgid "plan"
msgstr ""
-#: ../../app/controllers/application_controller.rb:129
+#: ../../app/controllers/application_controller.rb:136
msgid "guidance group"
msgstr ""
-#: ../../app/controllers/application_controller.rb:130
+#: ../../app/controllers/application_controller.rb:137
msgid "comment"
msgstr ""
-#: ../../app/controllers/application_controller.rb:131
+#: ../../app/controllers/application_controller.rb:138
msgid "organisation"
msgstr ""
-#: ../../app/controllers/application_controller.rb:132
+#: ../../app/controllers/application_controller.rb:139
msgid "permission"
msgstr ""
-#: ../../app/controllers/application_controller.rb:133
+#: ../../app/controllers/application_controller.rb:140
msgid "preferences"
msgstr ""
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "profile"
msgstr ""
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "user"
msgstr ""
-#: ../../app/controllers/application_controller.rb:135
+#: ../../app/controllers/application_controller.rb:142
msgid "question option"
msgstr ""
-#: ../../app/controllers/application_controller.rb:181
+#: ../../app/controllers/application_controller.rb:188
msgid "Record Not Found"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:45
+#: ../../app/controllers/concerns/paginable.rb:46
msgid "scope should be an ActiveRecord::Relation object"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:47
+#: ../../app/controllers/concerns/paginable.rb:48
msgid "path_params should be a Hash object"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:48
+#: ../../app/controllers/concerns/paginable.rb:49
msgid "query_params should be a Hash object"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:49
+#: ../../app/controllers/concerns/paginable.rb:50
msgid "locals should be a Hash object"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:70
+#: ../../app/controllers/concerns/paginable.rb:71
msgid "Restricted access to View All the records"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:183
+#: ../../app/controllers/concerns/paginable.rb:184
msgid "Sort by %{sort_field}"
msgstr ""
@@ -244,77 +252,77 @@ msgstr "Contact email was successfully sent."
msgid "Unable to submit your request"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:40
-#: ../../app/controllers/contributors_controller.rb:56
+#: ../../app/controllers/contributors_controller.rb:41
+#: ../../app/controllers/contributors_controller.rb:57
#: ../../app/controllers/research_outputs_controller.rb:42
msgid "add"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:54
+#: ../../app/controllers/contributors_controller.rb:55
#: ../../app/controllers/research_outputs_controller.rb:40
msgid "added"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:72
+#: ../../app/controllers/contributors_controller.rb:73
#: ../../app/controllers/guidance_groups_controller.rb:55
#: ../../app/controllers/guidances_controller.rb:75
-#: ../../app/controllers/notes_controller.rb:88
+#: ../../app/controllers/notes_controller.rb:89
#: ../../app/controllers/org_admin/departments_controller.rb:50
#: ../../app/controllers/org_admin/sections_controller.rb:103
#: ../../app/controllers/org_admin/templates_controller.rb:210
#: ../../app/controllers/orgs_controller.rb:92
-#: ../../app/controllers/plans_controller.rb:280
-#: ../../app/controllers/plans_controller.rb:283
+#: ../../app/controllers/plans_controller.rb:281
+#: ../../app/controllers/plans_controller.rb:284
#: ../../app/controllers/registrations_controller.rb:249
#: ../../app/controllers/registrations_controller.rb:253
#: ../../app/controllers/registrations_controller.rb:280
#: ../../app/controllers/registrations_controller.rb:284
#: ../../app/controllers/research_outputs_controller.rb:60
-#: ../../app/controllers/users_controller.rb:103
-#: ../../app/controllers/users_controller.rb:131
+#: ../../app/controllers/users_controller.rb:104
+#: ../../app/controllers/users_controller.rb:132
msgid "saved"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:74
+#: ../../app/controllers/contributors_controller.rb:75
#: ../../app/controllers/guidance_groups_controller.rb:57
#: ../../app/controllers/guidances_controller.rb:77
-#: ../../app/controllers/notes_controller.rb:106
+#: ../../app/controllers/notes_controller.rb:107
#: ../../app/controllers/org_admin/departments_controller.rb:52
#: ../../app/controllers/org_admin/sections_controller.rb:105
#: ../../app/controllers/org_admin/templates_controller.rb:215
#: ../../app/controllers/orgs_controller.rb:94
-#: ../../app/controllers/plans_controller.rb:289
-#: ../../app/controllers/plans_controller.rb:292
-#: ../../app/controllers/plans_controller.rb:296
-#: ../../app/controllers/plans_controller.rb:299
+#: ../../app/controllers/plans_controller.rb:290
+#: ../../app/controllers/plans_controller.rb:293
+#: ../../app/controllers/plans_controller.rb:297
+#: ../../app/controllers/plans_controller.rb:300
#: ../../app/controllers/registrations_controller.rb:256
#: ../../app/controllers/registrations_controller.rb:287
#: ../../app/controllers/research_outputs_controller.rb:63
msgid "save"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:83
-#: ../../app/controllers/notes_controller.rb:130
+#: ../../app/controllers/contributors_controller.rb:84
+#: ../../app/controllers/notes_controller.rb:131
#: ../../app/controllers/org_admin/templates_controller.rb:243
#: ../../app/controllers/research_outputs_controller.rb:74
#: ../../app/controllers/super_admin/orgs_controller.rb:94
msgid "removed"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:86
-#: ../../app/controllers/notes_controller.rb:148
+#: ../../app/controllers/contributors_controller.rb:87
+#: ../../app/controllers/notes_controller.rb:149
#: ../../app/controllers/org_admin/templates_controller.rb:245
#: ../../app/controllers/research_outputs_controller.rb:77
#: ../../app/controllers/super_admin/orgs_controller.rb:97
msgid "remove"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:160
+#: ../../app/controllers/contributors_controller.rb:161
#: ../../app/controllers/research_outputs_controller.rb:208
msgid "plan not found"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:168
+#: ../../app/controllers/contributors_controller.rb:169
msgid "contributor not found"
msgstr ""
@@ -328,7 +336,7 @@ msgstr ""
#: ../../app/controllers/guidance_groups_controller.rb:31
#: ../../app/controllers/guidances_controller.rb:53
-#: ../../app/controllers/notes_controller.rb:47
+#: ../../app/controllers/notes_controller.rb:48
#: ../../app/controllers/org_admin/departments_controller.rb:26
#: ../../app/controllers/org_admin/phases_controller.rb:121
#: ../../app/controllers/org_admin/questions_controller.rb:94
@@ -344,7 +352,7 @@ msgstr ""
#: ../../app/controllers/guidance_groups_controller.rb:34
#: ../../app/controllers/guidances_controller.rb:55
-#: ../../app/controllers/notes_controller.rb:66
+#: ../../app/controllers/notes_controller.rb:67
#: ../../app/controllers/org_admin/departments_controller.rb:30
#: ../../app/controllers/org_admin/phases_controller.rb:123
#: ../../app/controllers/org_admin/questions_controller.rb:96
@@ -383,7 +391,7 @@ msgstr ""
#: ../../app/controllers/org_admin/question_options_controller.rb:24
#: ../../app/controllers/org_admin/questions_controller.rb:197
#: ../../app/controllers/org_admin/sections_controller.rb:128
-#: ../../app/controllers/plans_controller.rb:342
+#: ../../app/controllers/plans_controller.rb:343
#: ../../app/controllers/super_admin/api_clients_controller.rb:81
#: ../../app/controllers/super_admin/notifications_controller.rb:85
#: ../../app/controllers/super_admin/themes_controller.rb:51
@@ -397,7 +405,7 @@ msgstr ""
#: ../../app/controllers/org_admin/question_options_controller.rb:26
#: ../../app/controllers/org_admin/questions_controller.rb:199
#: ../../app/controllers/org_admin/sections_controller.rb:130
-#: ../../app/controllers/plans_controller.rb:347
+#: ../../app/controllers/plans_controller.rb:348
#: ../../app/controllers/super_admin/api_clients_controller.rb:84
#: ../../app/controllers/super_admin/notifications_controller.rb:88
#: ../../app/controllers/super_admin/themes_controller.rb:54
@@ -438,19 +446,19 @@ msgstr ""
#: ../../app/controllers/org_admin/phases_controller.rb:147
#: ../../app/controllers/org_admin/questions_controller.rb:166
#: ../../app/controllers/org_admin/users_controller.rb:30
-#: ../../app/controllers/plans_controller.rb:416
+#: ../../app/controllers/plans_controller.rb:417
#: ../../app/controllers/super_admin/api_clients_controller.rb:68
#: ../../app/controllers/super_admin/notifications_controller.rb:52
#: ../../app/controllers/super_admin/themes_controller.rb:39
#: ../../app/controllers/super_admin/users_controller.rb:54
-#: ../../app/controllers/users_controller.rb:108
+#: ../../app/controllers/users_controller.rb:109
msgid "updated"
msgstr ""
#: ../../app/controllers/org_admin/phases_controller.rb:149
#: ../../app/controllers/org_admin/questions_controller.rb:169
#: ../../app/controllers/org_admin/users_controller.rb:32
-#: ../../app/controllers/plans_controller.rb:419
+#: ../../app/controllers/plans_controller.rb:420
#: ../../app/controllers/super_admin/api_clients_controller.rb:70
#: ../../app/controllers/super_admin/notifications_controller.rb:55
#: ../../app/controllers/super_admin/themes_controller.rb:41
@@ -540,7 +548,7 @@ msgid "Unable to delete this version of the template."
msgstr ""
#: ../../app/controllers/org_admin/template_copies_controller.rb:20
-#: ../../app/controllers/plans_controller.rb:395
+#: ../../app/controllers/plans_controller.rb:396
msgid "copy"
msgstr ""
@@ -549,11 +557,11 @@ msgstr ""
msgid "That template is no longer customizable."
msgstr "That template is no longer customisable."
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:21
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:22
msgid "Unable to customize that template."
msgstr "Unable to customise that template"
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:24
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:25
msgid "That template is not customizable."
msgstr "That template is not customisable"
@@ -643,33 +651,33 @@ msgstr ""
msgid "template with customisations by the"
msgstr ""
-#: ../../app/controllers/plans_controller.rb:393
+#: ../../app/controllers/plans_controller.rb:394
msgid "copied"
msgstr ""
-#: ../../app/controllers/plans_controller.rb:424
+#: ../../app/controllers/plans_controller.rb:425
msgid ""
"Unable to change the plan's status since it is needed at least %{percentage} p"
"ercentage responded"
msgstr ""
-#: ../../app/controllers/plans_controller.rb:430
+#: ../../app/controllers/plans_controller.rb:431
msgid "Unable to find plan id %{plan_id}"
msgstr ""
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is now a test."
msgstr ""
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is no longer a test."
msgstr ""
-#: ../../app/controllers/plans_controller.rb:449
+#: ../../app/controllers/plans_controller.rb:450
msgid "Unable to change the plan's test status"
msgstr ""
-#: ../../app/controllers/plans_controller.rb:462
+#: ../../app/controllers/plans_controller.rb:463
msgid "There is no plan associated with id %{s"
msgstr ""
@@ -754,7 +762,7 @@ msgstr ""
msgid "research output not found"
msgstr ""
-#: ../../app/controllers/roles_controller.rb:26
+#: ../../app/controllers/roles_controller.rb:27
msgid ""
"Cannot share plan with %{email} since that email matches\n"
" with the owner of the plan."
@@ -917,27 +925,27 @@ msgstr ""
msgid "Unable to link your account to %{scheme}."
msgstr ""
-#: ../../app/controllers/users_controller.rb:149
+#: ../../app/controllers/users_controller.rb:150
msgid "Successfully %{action} %{username}'s account."
msgstr ""
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "activated"
msgstr ""
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "deactivated"
msgstr ""
-#: ../../app/controllers/users_controller.rb:156
+#: ../../app/controllers/users_controller.rb:157
msgid "Unable to %{action} %{username}"
msgstr ""
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "activate"
msgstr ""
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "deactivate"
msgstr ""
@@ -1217,50 +1225,50 @@ msgstr ""
msgid "Last 12 months"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:17
+#: ../../app/mailers/user_mailer.rb:18
#: ../../app/views/devise/mailer/invitation_instructions.html.erb:5
#: ../../app/views/devise/mailer/reset_password_instructions.html.erb:5
#: ../../app/views/user_mailer/_email_signature.html.erb:2
msgid "Query or feedback related to %{tool_name}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:25
+#: ../../app/mailers/user_mailer.rb:26
msgid "Welcome to %{tool_name}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:62
+#: ../../app/mailers/user_mailer.rb:63
msgid "A Data Management Plan in %{tool_name} has been shared with you"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:79
+#: ../../app/mailers/user_mailer.rb:80
msgid "Changed permissions on a Data Management Plan in %{tool_name}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:94
+#: ../../app/mailers/user_mailer.rb:95
msgid "Permissions removed on a DMP in %{tool_name}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:112
+#: ../../app/mailers/user_mailer.rb:113
msgid "%{user_name} has requested feedback on a %{tool_name} plan"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:135
+#: ../../app/mailers/user_mailer.rb:136
msgid "%{tool_name}: Expert feedback has been provided for %{plan_title}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:153
+#: ../../app/mailers/user_mailer.rb:154
msgid "DMP Visibility Changed: %{plan_title}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:182
+#: ../../app/mailers/user_mailer.rb:183
msgid "%{tool_name}: A new comment was added to %{plan_title}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:198
+#: ../../app/mailers/user_mailer.rb:199
msgid "Administrator privileges granted in %{tool_name}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:216
+#: ../../app/mailers/user_mailer.rb:217
msgid "%{tool_name} API changes"
msgstr ""
@@ -1490,15 +1498,15 @@ msgstr ""
msgid "already assigned a value"
msgstr ""
-#: ../../app/models/org.rb:46
+#: ../../app/models/org.rb:47
msgid "Feedback email message"
msgstr ""
-#: ../../app/models/org.rb:123
+#: ../../app/models/org.rb:124
msgid "must be one of the following formats: jpeg, jpg, png, gif, bmp"
msgstr ""
-#: ../../app/models/org.rb:128
+#: ../../app/models/org.rb:129
msgid "can't be larger than 500KB"
msgstr ""
@@ -1622,7 +1630,7 @@ msgstr ""
msgid "Conditions in the template refer backwards"
msgstr ""
-#: ../../app/models/user.rb:380
+#: ../../app/models/user.rb:386
msgid "A Data Management Plan in %{application_name} has been shared with you"
msgstr ""
@@ -2032,7 +2040,7 @@ msgstr ""
#: ../../app/views/paginable/templates/_organisational.html.erb:87
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:29
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:36
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
#: ../../app/views/static_pages/about_us.html.erb:22
#: ../../app/views/static_pages/about_us.html.erb:29
#: ../../app/views/static_pages/termsuse.html.erb:46
@@ -4353,7 +4361,7 @@ msgstr ""
msgid "Instructions"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:6
+#: ../../app/views/plans/_download_form.html.erb:5
msgid "Format"
msgstr ""
@@ -4361,71 +4369,71 @@ msgstr ""
msgid "Download settings"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:19
-msgid "Select phase to download"
-msgstr ""
-
-#: ../../app/views/plans/_download_form.html.erb:26
+#: ../../app/views/plans/_download_form.html.erb:21
msgid "Optional plan components"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:30
+#: ../../app/views/plans/_download_form.html.erb:25
msgid "project details coversheet"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:36
+#: ../../app/views/plans/_download_form.html.erb:31
msgid "question text and section headings"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:42
+#: ../../app/views/plans/_download_form.html.erb:37
msgid "unanswered questions"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:49
+#: ../../app/views/plans/_download_form.html.erb:44
msgid "research outputs"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:57
+#: ../../app/views/plans/_download_form.html.erb:52
msgid "supplementary section(s) not requested by funding organisation"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:65
+#: ../../app/views/plans/_download_form.html.erb:61
+msgid "Select phase to download"
+msgstr ""
+
+#: ../../app/views/plans/_download_form.html.erb:70
msgid "PDF formatting"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:68
+#: ../../app/views/plans/_download_form.html.erb:73
msgid "Font"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:71
+#: ../../app/views/plans/_download_form.html.erb:76
msgid "Margin (mm)"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:76
+#: ../../app/views/plans/_download_form.html.erb:81
msgid "Face"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:84
+#: ../../app/views/plans/_download_form.html.erb:89
msgid "Size"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:92
+#: ../../app/views/plans/_download_form.html.erb:96
msgid "Top"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:101
+#: ../../app/views/plans/_download_form.html.erb:105
msgid "Bottom"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:110
+#: ../../app/views/plans/_download_form.html.erb:114
msgid "Left"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:119
+#: ../../app/views/plans/_download_form.html.erb:123
msgid "Right"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
msgid ""
"Download Plan (new window)%{open_in_new_window_text}"
diff --git a/config/locale/en_US/LC_MESSAGES/app.mo b/config/locale/en_US/LC_MESSAGES/app.mo
index 4312126274..e5c4383c22 100644
Binary files a/config/locale/en_US/LC_MESSAGES/app.mo and b/config/locale/en_US/LC_MESSAGES/app.mo differ
diff --git a/config/locale/en_US/app.po b/config/locale/en_US/app.po
index 1626c14e2e..321ef003b5 100644
--- a/config/locale/en_US/app.po
+++ b/config/locale/en_US/app.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: roadmap_upstream 1.0\n"
"Report-Msgid-Bugs-To: contact@translation.io\n"
-"POT-Creation-Date: 2025-04-10 13:28-0600\n"
-"PO-Revision-Date: 2025-04-10 21:28+0200\n"
+"POT-Creation-Date: 2025-12-23 08:33-0700\n"
+"PO-Revision-Date: 2025-12-23 15:33+0000\n"
"Last-Translator: FULL NAME \n"
"Language-Team: English\n"
"Language: en_US\n"
@@ -123,87 +123,95 @@ msgstr ""
msgid "No Plans found"
msgstr ""
-#: ../../app/controllers/application_controller.rb:36
+#: ../../app/controllers/api/v2/base_api_controller.rb:72
+msgid "There was a problem in the server."
+msgstr ""
+
+#: ../../app/controllers/api/v2/base_api_controller.rb:78
+msgid "The client is not authorized to perform this action."
+msgstr ""
+
+#: ../../app/controllers/application_controller.rb:37
msgid "You are not authorized to perform this action."
msgstr ""
-#: ../../app/controllers/application_controller.rb:40
+#: ../../app/controllers/application_controller.rb:41
msgid "You need to sign in or sign up before continuing."
msgstr "You need to sign in or sign up before continuing."
-#: ../../app/controllers/application_controller.rb:108
+#: ../../app/controllers/application_controller.rb:115
msgid "Unable to %{action} the %{object}. %{errors}"
msgstr ""
-#: ../../app/controllers/application_controller.rb:114
+#: ../../app/controllers/application_controller.rb:121
msgid "Successfully %{action} the %{object}."
msgstr ""
-#: ../../app/controllers/application_controller.rb:127
+#: ../../app/controllers/application_controller.rb:134
msgid "API client"
msgstr ""
-#: ../../app/controllers/application_controller.rb:128
+#: ../../app/controllers/application_controller.rb:135
msgid "plan"
msgstr ""
-#: ../../app/controllers/application_controller.rb:129
+#: ../../app/controllers/application_controller.rb:136
msgid "guidance group"
msgstr ""
-#: ../../app/controllers/application_controller.rb:130
+#: ../../app/controllers/application_controller.rb:137
msgid "comment"
msgstr ""
-#: ../../app/controllers/application_controller.rb:131
+#: ../../app/controllers/application_controller.rb:138
msgid "organisation"
msgstr "organization"
-#: ../../app/controllers/application_controller.rb:132
+#: ../../app/controllers/application_controller.rb:139
msgid "permission"
msgstr ""
-#: ../../app/controllers/application_controller.rb:133
+#: ../../app/controllers/application_controller.rb:140
msgid "preferences"
msgstr ""
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "profile"
msgstr ""
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "user"
msgstr ""
-#: ../../app/controllers/application_controller.rb:135
+#: ../../app/controllers/application_controller.rb:142
msgid "question option"
msgstr ""
-#: ../../app/controllers/application_controller.rb:181
+#: ../../app/controllers/application_controller.rb:188
msgid "Record Not Found"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:45
+#: ../../app/controllers/concerns/paginable.rb:46
msgid "scope should be an ActiveRecord::Relation object"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:47
+#: ../../app/controllers/concerns/paginable.rb:48
msgid "path_params should be a Hash object"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:48
+#: ../../app/controllers/concerns/paginable.rb:49
msgid "query_params should be a Hash object"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:49
+#: ../../app/controllers/concerns/paginable.rb:50
msgid "locals should be a Hash object"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:70
+#: ../../app/controllers/concerns/paginable.rb:71
msgid "Restricted access to View All the records"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:183
+#: ../../app/controllers/concerns/paginable.rb:184
msgid "Sort by %{sort_field}"
msgstr ""
@@ -244,77 +252,77 @@ msgstr "Contact email was successfully sent."
msgid "Unable to submit your request"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:40
-#: ../../app/controllers/contributors_controller.rb:56
+#: ../../app/controllers/contributors_controller.rb:41
+#: ../../app/controllers/contributors_controller.rb:57
#: ../../app/controllers/research_outputs_controller.rb:42
msgid "add"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:54
+#: ../../app/controllers/contributors_controller.rb:55
#: ../../app/controllers/research_outputs_controller.rb:40
msgid "added"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:72
+#: ../../app/controllers/contributors_controller.rb:73
#: ../../app/controllers/guidance_groups_controller.rb:55
#: ../../app/controllers/guidances_controller.rb:75
-#: ../../app/controllers/notes_controller.rb:88
+#: ../../app/controllers/notes_controller.rb:89
#: ../../app/controllers/org_admin/departments_controller.rb:50
#: ../../app/controllers/org_admin/sections_controller.rb:103
#: ../../app/controllers/org_admin/templates_controller.rb:210
#: ../../app/controllers/orgs_controller.rb:92
-#: ../../app/controllers/plans_controller.rb:280
-#: ../../app/controllers/plans_controller.rb:283
+#: ../../app/controllers/plans_controller.rb:281
+#: ../../app/controllers/plans_controller.rb:284
#: ../../app/controllers/registrations_controller.rb:249
#: ../../app/controllers/registrations_controller.rb:253
#: ../../app/controllers/registrations_controller.rb:280
#: ../../app/controllers/registrations_controller.rb:284
#: ../../app/controllers/research_outputs_controller.rb:60
-#: ../../app/controllers/users_controller.rb:103
-#: ../../app/controllers/users_controller.rb:131
+#: ../../app/controllers/users_controller.rb:104
+#: ../../app/controllers/users_controller.rb:132
msgid "saved"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:74
+#: ../../app/controllers/contributors_controller.rb:75
#: ../../app/controllers/guidance_groups_controller.rb:57
#: ../../app/controllers/guidances_controller.rb:77
-#: ../../app/controllers/notes_controller.rb:106
+#: ../../app/controllers/notes_controller.rb:107
#: ../../app/controllers/org_admin/departments_controller.rb:52
#: ../../app/controllers/org_admin/sections_controller.rb:105
#: ../../app/controllers/org_admin/templates_controller.rb:215
#: ../../app/controllers/orgs_controller.rb:94
-#: ../../app/controllers/plans_controller.rb:289
-#: ../../app/controllers/plans_controller.rb:292
-#: ../../app/controllers/plans_controller.rb:296
-#: ../../app/controllers/plans_controller.rb:299
+#: ../../app/controllers/plans_controller.rb:290
+#: ../../app/controllers/plans_controller.rb:293
+#: ../../app/controllers/plans_controller.rb:297
+#: ../../app/controllers/plans_controller.rb:300
#: ../../app/controllers/registrations_controller.rb:256
#: ../../app/controllers/registrations_controller.rb:287
#: ../../app/controllers/research_outputs_controller.rb:63
msgid "save"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:83
-#: ../../app/controllers/notes_controller.rb:130
+#: ../../app/controllers/contributors_controller.rb:84
+#: ../../app/controllers/notes_controller.rb:131
#: ../../app/controllers/org_admin/templates_controller.rb:243
#: ../../app/controllers/research_outputs_controller.rb:74
#: ../../app/controllers/super_admin/orgs_controller.rb:94
msgid "removed"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:86
-#: ../../app/controllers/notes_controller.rb:148
+#: ../../app/controllers/contributors_controller.rb:87
+#: ../../app/controllers/notes_controller.rb:149
#: ../../app/controllers/org_admin/templates_controller.rb:245
#: ../../app/controllers/research_outputs_controller.rb:77
#: ../../app/controllers/super_admin/orgs_controller.rb:97
msgid "remove"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:160
+#: ../../app/controllers/contributors_controller.rb:161
#: ../../app/controllers/research_outputs_controller.rb:208
msgid "plan not found"
msgstr ""
-#: ../../app/controllers/contributors_controller.rb:168
+#: ../../app/controllers/contributors_controller.rb:169
msgid "contributor not found"
msgstr ""
@@ -328,7 +336,7 @@ msgstr ""
#: ../../app/controllers/guidance_groups_controller.rb:31
#: ../../app/controllers/guidances_controller.rb:53
-#: ../../app/controllers/notes_controller.rb:47
+#: ../../app/controllers/notes_controller.rb:48
#: ../../app/controllers/org_admin/departments_controller.rb:26
#: ../../app/controllers/org_admin/phases_controller.rb:121
#: ../../app/controllers/org_admin/questions_controller.rb:94
@@ -344,7 +352,7 @@ msgstr ""
#: ../../app/controllers/guidance_groups_controller.rb:34
#: ../../app/controllers/guidances_controller.rb:55
-#: ../../app/controllers/notes_controller.rb:66
+#: ../../app/controllers/notes_controller.rb:67
#: ../../app/controllers/org_admin/departments_controller.rb:30
#: ../../app/controllers/org_admin/phases_controller.rb:123
#: ../../app/controllers/org_admin/questions_controller.rb:96
@@ -383,7 +391,7 @@ msgstr ""
#: ../../app/controllers/org_admin/question_options_controller.rb:24
#: ../../app/controllers/org_admin/questions_controller.rb:197
#: ../../app/controllers/org_admin/sections_controller.rb:128
-#: ../../app/controllers/plans_controller.rb:342
+#: ../../app/controllers/plans_controller.rb:343
#: ../../app/controllers/super_admin/api_clients_controller.rb:81
#: ../../app/controllers/super_admin/notifications_controller.rb:85
#: ../../app/controllers/super_admin/themes_controller.rb:51
@@ -397,7 +405,7 @@ msgstr ""
#: ../../app/controllers/org_admin/question_options_controller.rb:26
#: ../../app/controllers/org_admin/questions_controller.rb:199
#: ../../app/controllers/org_admin/sections_controller.rb:130
-#: ../../app/controllers/plans_controller.rb:347
+#: ../../app/controllers/plans_controller.rb:348
#: ../../app/controllers/super_admin/api_clients_controller.rb:84
#: ../../app/controllers/super_admin/notifications_controller.rb:88
#: ../../app/controllers/super_admin/themes_controller.rb:54
@@ -438,19 +446,19 @@ msgstr ""
#: ../../app/controllers/org_admin/phases_controller.rb:147
#: ../../app/controllers/org_admin/questions_controller.rb:166
#: ../../app/controllers/org_admin/users_controller.rb:30
-#: ../../app/controllers/plans_controller.rb:416
+#: ../../app/controllers/plans_controller.rb:417
#: ../../app/controllers/super_admin/api_clients_controller.rb:68
#: ../../app/controllers/super_admin/notifications_controller.rb:52
#: ../../app/controllers/super_admin/themes_controller.rb:39
#: ../../app/controllers/super_admin/users_controller.rb:54
-#: ../../app/controllers/users_controller.rb:108
+#: ../../app/controllers/users_controller.rb:109
msgid "updated"
msgstr ""
#: ../../app/controllers/org_admin/phases_controller.rb:149
#: ../../app/controllers/org_admin/questions_controller.rb:169
#: ../../app/controllers/org_admin/users_controller.rb:32
-#: ../../app/controllers/plans_controller.rb:419
+#: ../../app/controllers/plans_controller.rb:420
#: ../../app/controllers/super_admin/api_clients_controller.rb:70
#: ../../app/controllers/super_admin/notifications_controller.rb:55
#: ../../app/controllers/super_admin/themes_controller.rb:41
@@ -540,7 +548,7 @@ msgid "Unable to delete this version of the template."
msgstr ""
#: ../../app/controllers/org_admin/template_copies_controller.rb:20
-#: ../../app/controllers/plans_controller.rb:395
+#: ../../app/controllers/plans_controller.rb:396
msgid "copy"
msgstr ""
@@ -549,11 +557,11 @@ msgstr ""
msgid "That template is no longer customizable."
msgstr "That template is no longer customizable."
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:21
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:22
msgid "Unable to customize that template."
msgstr "Unable to customize that template."
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:24
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:25
msgid "That template is not customizable."
msgstr "That template is not customizable."
@@ -643,33 +651,33 @@ msgstr ""
msgid "template with customisations by the"
msgstr ""
-#: ../../app/controllers/plans_controller.rb:393
+#: ../../app/controllers/plans_controller.rb:394
msgid "copied"
msgstr ""
-#: ../../app/controllers/plans_controller.rb:424
+#: ../../app/controllers/plans_controller.rb:425
msgid ""
"Unable to change the plan's status since it is needed at least %{percentage} p"
"ercentage responded"
msgstr ""
-#: ../../app/controllers/plans_controller.rb:430
+#: ../../app/controllers/plans_controller.rb:431
msgid "Unable to find plan id %{plan_id}"
msgstr ""
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is now a test."
msgstr ""
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is no longer a test."
msgstr ""
-#: ../../app/controllers/plans_controller.rb:449
+#: ../../app/controllers/plans_controller.rb:450
msgid "Unable to change the plan's test status"
msgstr ""
-#: ../../app/controllers/plans_controller.rb:462
+#: ../../app/controllers/plans_controller.rb:463
msgid "There is no plan associated with id %{s"
msgstr ""
@@ -756,7 +764,7 @@ msgstr ""
msgid "research output not found"
msgstr ""
-#: ../../app/controllers/roles_controller.rb:26
+#: ../../app/controllers/roles_controller.rb:27
msgid ""
"Cannot share plan with %{email} since that email matches\n"
" with the owner of the plan."
@@ -921,27 +929,27 @@ msgstr ""
msgid "Unable to link your account to %{scheme}."
msgstr ""
-#: ../../app/controllers/users_controller.rb:149
+#: ../../app/controllers/users_controller.rb:150
msgid "Successfully %{action} %{username}'s account."
msgstr ""
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "activated"
msgstr ""
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "deactivated"
msgstr ""
-#: ../../app/controllers/users_controller.rb:156
+#: ../../app/controllers/users_controller.rb:157
msgid "Unable to %{action} %{username}"
msgstr ""
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "activate"
msgstr ""
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "deactivate"
msgstr ""
@@ -1221,50 +1229,50 @@ msgstr ""
msgid "Last 12 months"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:17
+#: ../../app/mailers/user_mailer.rb:18
#: ../../app/views/devise/mailer/invitation_instructions.html.erb:5
#: ../../app/views/devise/mailer/reset_password_instructions.html.erb:5
#: ../../app/views/user_mailer/_email_signature.html.erb:2
msgid "Query or feedback related to %{tool_name}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:25
+#: ../../app/mailers/user_mailer.rb:26
msgid "Welcome to %{tool_name}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:62
+#: ../../app/mailers/user_mailer.rb:63
msgid "A Data Management Plan in %{tool_name} has been shared with you"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:79
+#: ../../app/mailers/user_mailer.rb:80
msgid "Changed permissions on a Data Management Plan in %{tool_name}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:94
+#: ../../app/mailers/user_mailer.rb:95
msgid "Permissions removed on a DMP in %{tool_name}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:112
+#: ../../app/mailers/user_mailer.rb:113
msgid "%{user_name} has requested feedback on a %{tool_name} plan"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:135
+#: ../../app/mailers/user_mailer.rb:136
msgid "%{tool_name}: Expert feedback has been provided for %{plan_title}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:153
+#: ../../app/mailers/user_mailer.rb:154
msgid "DMP Visibility Changed: %{plan_title}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:182
+#: ../../app/mailers/user_mailer.rb:183
msgid "%{tool_name}: A new comment was added to %{plan_title}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:198
+#: ../../app/mailers/user_mailer.rb:199
msgid "Administrator privileges granted in %{tool_name}"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:216
+#: ../../app/mailers/user_mailer.rb:217
msgid "%{tool_name} API changes"
msgstr ""
@@ -1494,15 +1502,15 @@ msgstr ""
msgid "already assigned a value"
msgstr ""
-#: ../../app/models/org.rb:46
+#: ../../app/models/org.rb:47
msgid "Feedback email message"
msgstr ""
-#: ../../app/models/org.rb:123
+#: ../../app/models/org.rb:124
msgid "must be one of the following formats: jpeg, jpg, png, gif, bmp"
msgstr ""
-#: ../../app/models/org.rb:128
+#: ../../app/models/org.rb:129
msgid "can't be larger than 500KB"
msgstr ""
@@ -1626,7 +1634,7 @@ msgstr ""
msgid "Conditions in the template refer backwards"
msgstr ""
-#: ../../app/models/user.rb:380
+#: ../../app/models/user.rb:386
msgid "A Data Management Plan in %{application_name} has been shared with you"
msgstr ""
@@ -2036,7 +2044,7 @@ msgstr ""
#: ../../app/views/paginable/templates/_organisational.html.erb:87
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:29
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:36
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
#: ../../app/views/static_pages/about_us.html.erb:22
#: ../../app/views/static_pages/about_us.html.erb:29
#: ../../app/views/static_pages/termsuse.html.erb:46
@@ -4396,7 +4404,7 @@ msgstr ""
msgid "Instructions"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:6
+#: ../../app/views/plans/_download_form.html.erb:5
msgid "Format"
msgstr ""
@@ -4404,71 +4412,71 @@ msgstr ""
msgid "Download settings"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:19
-msgid "Select phase to download"
-msgstr ""
-
-#: ../../app/views/plans/_download_form.html.erb:26
+#: ../../app/views/plans/_download_form.html.erb:21
msgid "Optional plan components"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:30
+#: ../../app/views/plans/_download_form.html.erb:25
msgid "project details coversheet"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:36
+#: ../../app/views/plans/_download_form.html.erb:31
msgid "question text and section headings"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:42
+#: ../../app/views/plans/_download_form.html.erb:37
msgid "unanswered questions"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:49
+#: ../../app/views/plans/_download_form.html.erb:44
msgid "research outputs"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:57
+#: ../../app/views/plans/_download_form.html.erb:52
msgid "supplementary section(s) not requested by funding organisation"
msgstr "supplementary section(s) not requested by funding organization"
-#: ../../app/views/plans/_download_form.html.erb:65
+#: ../../app/views/plans/_download_form.html.erb:61
+msgid "Select phase to download"
+msgstr ""
+
+#: ../../app/views/plans/_download_form.html.erb:70
msgid "PDF formatting"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:68
+#: ../../app/views/plans/_download_form.html.erb:73
msgid "Font"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:71
+#: ../../app/views/plans/_download_form.html.erb:76
msgid "Margin (mm)"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:76
+#: ../../app/views/plans/_download_form.html.erb:81
msgid "Face"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:84
+#: ../../app/views/plans/_download_form.html.erb:89
msgid "Size"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:92
+#: ../../app/views/plans/_download_form.html.erb:96
msgid "Top"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:101
+#: ../../app/views/plans/_download_form.html.erb:105
msgid "Bottom"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:110
+#: ../../app/views/plans/_download_form.html.erb:114
msgid "Left"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:119
+#: ../../app/views/plans/_download_form.html.erb:123
msgid "Right"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
msgid ""
"Download Plan (new window)%{open_in_new_window_text}"
diff --git a/config/locale/es/LC_MESSAGES/app.mo b/config/locale/es/LC_MESSAGES/app.mo
index 7199660719..5da2fa1dff 100644
Binary files a/config/locale/es/LC_MESSAGES/app.mo and b/config/locale/es/LC_MESSAGES/app.mo differ
diff --git a/config/locale/es/app.po b/config/locale/es/app.po
index d381a6a36e..bd30a3a3bb 100644
--- a/config/locale/es/app.po
+++ b/config/locale/es/app.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: roadmap_upstream 1.0\n"
"Report-Msgid-Bugs-To: contact@translation.io\n"
-"POT-Creation-Date: 2025-04-10 13:28-0600\n"
-"PO-Revision-Date: 2025-04-10 21:28+0200\n"
+"POT-Creation-Date: 2025-12-23 08:33-0700\n"
+"PO-Revision-Date: 2025-12-23 15:33+0000\n"
"Last-Translator: FULL NAME \n"
"Language-Team: Spanish\n"
"Language: es\n"
@@ -127,87 +127,95 @@ msgstr "JSON inválido"
msgid "No Plans found"
msgstr "No se encontraron planes"
-#: ../../app/controllers/application_controller.rb:36
+#: ../../app/controllers/api/v2/base_api_controller.rb:72
+msgid "There was a problem in the server."
+msgstr ""
+
+#: ../../app/controllers/api/v2/base_api_controller.rb:78
+msgid "The client is not authorized to perform this action."
+msgstr ""
+
+#: ../../app/controllers/application_controller.rb:37
msgid "You are not authorized to perform this action."
msgstr "Usted no está autorizado para realizar esta acción."
-#: ../../app/controllers/application_controller.rb:40
+#: ../../app/controllers/application_controller.rb:41
msgid "You need to sign in or sign up before continuing."
msgstr "Necesita iniciar sesión o registrarse para continuar."
-#: ../../app/controllers/application_controller.rb:108
+#: ../../app/controllers/application_controller.rb:115
msgid "Unable to %{action} the %{object}. %{errors}"
msgstr "No se puede %{action} el %{object}. %{errors}"
-#: ../../app/controllers/application_controller.rb:114
+#: ../../app/controllers/application_controller.rb:121
msgid "Successfully %{action} the %{object}."
msgstr "Con éxito %{action} el %{object}."
-#: ../../app/controllers/application_controller.rb:127
+#: ../../app/controllers/application_controller.rb:134
msgid "API client"
msgstr "Cliente API"
-#: ../../app/controllers/application_controller.rb:128
+#: ../../app/controllers/application_controller.rb:135
msgid "plan"
msgstr "Plan"
-#: ../../app/controllers/application_controller.rb:129
+#: ../../app/controllers/application_controller.rb:136
msgid "guidance group"
msgstr "grupo de orientación"
-#: ../../app/controllers/application_controller.rb:130
+#: ../../app/controllers/application_controller.rb:137
msgid "comment"
msgstr "Comentario"
-#: ../../app/controllers/application_controller.rb:131
+#: ../../app/controllers/application_controller.rb:138
msgid "organisation"
msgstr "organización"
-#: ../../app/controllers/application_controller.rb:132
+#: ../../app/controllers/application_controller.rb:139
msgid "permission"
msgstr "permiso"
-#: ../../app/controllers/application_controller.rb:133
+#: ../../app/controllers/application_controller.rb:140
msgid "preferences"
msgstr "Preferencias"
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "profile"
msgstr "Perfil"
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "user"
msgstr "user"
-#: ../../app/controllers/application_controller.rb:135
+#: ../../app/controllers/application_controller.rb:142
msgid "question option"
msgstr "opción de pregunta"
-#: ../../app/controllers/application_controller.rb:181
+#: ../../app/controllers/application_controller.rb:188
msgid "Record Not Found"
msgstr "Registro no encontrado"
-#: ../../app/controllers/concerns/paginable.rb:45
+#: ../../app/controllers/concerns/paginable.rb:46
msgid "scope should be an ActiveRecord::Relation object"
msgstr "el alcance debe ser un objeto ActiveRecord :: Relation"
-#: ../../app/controllers/concerns/paginable.rb:47
+#: ../../app/controllers/concerns/paginable.rb:48
msgid "path_params should be a Hash object"
msgstr "path_params debe ser un objeto Hash"
-#: ../../app/controllers/concerns/paginable.rb:48
+#: ../../app/controllers/concerns/paginable.rb:49
msgid "query_params should be a Hash object"
msgstr "query_params debe ser un objeto Hash"
-#: ../../app/controllers/concerns/paginable.rb:49
+#: ../../app/controllers/concerns/paginable.rb:50
msgid "locals should be a Hash object"
msgstr "los locales deberían ser un objeto Hash"
-#: ../../app/controllers/concerns/paginable.rb:70
+#: ../../app/controllers/concerns/paginable.rb:71
msgid "Restricted access to View All the records"
msgstr "Acceso restringido a Ver todos los registros."
-#: ../../app/controllers/concerns/paginable.rb:183
+#: ../../app/controllers/concerns/paginable.rb:184
msgid "Sort by %{sort_field}"
msgstr "Ordenar por %{sort_field}"
@@ -248,77 +256,77 @@ msgstr "El correo electrónico de contacto fue enviado con éxito."
msgid "Unable to submit your request"
msgstr "No se puede enviar su solicitud"
-#: ../../app/controllers/contributors_controller.rb:40
-#: ../../app/controllers/contributors_controller.rb:56
+#: ../../app/controllers/contributors_controller.rb:41
+#: ../../app/controllers/contributors_controller.rb:57
#: ../../app/controllers/research_outputs_controller.rb:42
msgid "add"
msgstr "Añadir"
-#: ../../app/controllers/contributors_controller.rb:54
+#: ../../app/controllers/contributors_controller.rb:55
#: ../../app/controllers/research_outputs_controller.rb:40
msgid "added"
msgstr "Adicional"
-#: ../../app/controllers/contributors_controller.rb:72
+#: ../../app/controllers/contributors_controller.rb:73
#: ../../app/controllers/guidance_groups_controller.rb:55
#: ../../app/controllers/guidances_controller.rb:75
-#: ../../app/controllers/notes_controller.rb:88
+#: ../../app/controllers/notes_controller.rb:89
#: ../../app/controllers/org_admin/departments_controller.rb:50
#: ../../app/controllers/org_admin/sections_controller.rb:103
#: ../../app/controllers/org_admin/templates_controller.rb:210
#: ../../app/controllers/orgs_controller.rb:92
-#: ../../app/controllers/plans_controller.rb:280
-#: ../../app/controllers/plans_controller.rb:283
+#: ../../app/controllers/plans_controller.rb:281
+#: ../../app/controllers/plans_controller.rb:284
#: ../../app/controllers/registrations_controller.rb:249
#: ../../app/controllers/registrations_controller.rb:253
#: ../../app/controllers/registrations_controller.rb:280
#: ../../app/controllers/registrations_controller.rb:284
#: ../../app/controllers/research_outputs_controller.rb:60
-#: ../../app/controllers/users_controller.rb:103
-#: ../../app/controllers/users_controller.rb:131
+#: ../../app/controllers/users_controller.rb:104
+#: ../../app/controllers/users_controller.rb:132
msgid "saved"
msgstr "Guardado"
-#: ../../app/controllers/contributors_controller.rb:74
+#: ../../app/controllers/contributors_controller.rb:75
#: ../../app/controllers/guidance_groups_controller.rb:57
#: ../../app/controllers/guidances_controller.rb:77
-#: ../../app/controllers/notes_controller.rb:106
+#: ../../app/controllers/notes_controller.rb:107
#: ../../app/controllers/org_admin/departments_controller.rb:52
#: ../../app/controllers/org_admin/sections_controller.rb:105
#: ../../app/controllers/org_admin/templates_controller.rb:215
#: ../../app/controllers/orgs_controller.rb:94
-#: ../../app/controllers/plans_controller.rb:289
-#: ../../app/controllers/plans_controller.rb:292
-#: ../../app/controllers/plans_controller.rb:296
-#: ../../app/controllers/plans_controller.rb:299
+#: ../../app/controllers/plans_controller.rb:290
+#: ../../app/controllers/plans_controller.rb:293
+#: ../../app/controllers/plans_controller.rb:297
+#: ../../app/controllers/plans_controller.rb:300
#: ../../app/controllers/registrations_controller.rb:256
#: ../../app/controllers/registrations_controller.rb:287
#: ../../app/controllers/research_outputs_controller.rb:63
msgid "save"
msgstr "Guardar"
-#: ../../app/controllers/contributors_controller.rb:83
-#: ../../app/controllers/notes_controller.rb:130
+#: ../../app/controllers/contributors_controller.rb:84
+#: ../../app/controllers/notes_controller.rb:131
#: ../../app/controllers/org_admin/templates_controller.rb:243
#: ../../app/controllers/research_outputs_controller.rb:74
#: ../../app/controllers/super_admin/orgs_controller.rb:94
msgid "removed"
msgstr "remoto"
-#: ../../app/controllers/contributors_controller.rb:86
-#: ../../app/controllers/notes_controller.rb:148
+#: ../../app/controllers/contributors_controller.rb:87
+#: ../../app/controllers/notes_controller.rb:149
#: ../../app/controllers/org_admin/templates_controller.rb:245
#: ../../app/controllers/research_outputs_controller.rb:77
#: ../../app/controllers/super_admin/orgs_controller.rb:97
msgid "remove"
msgstr "Quitar"
-#: ../../app/controllers/contributors_controller.rb:160
+#: ../../app/controllers/contributors_controller.rb:161
#: ../../app/controllers/research_outputs_controller.rb:208
msgid "plan not found"
msgstr "Plan no encontrado"
-#: ../../app/controllers/contributors_controller.rb:168
+#: ../../app/controllers/contributors_controller.rb:169
msgid "contributor not found"
msgstr "contribuyente no encontrado"
@@ -332,7 +340,7 @@ msgstr "Se produjo un error al solicitar comentarios para este plan."
#: ../../app/controllers/guidance_groups_controller.rb:31
#: ../../app/controllers/guidances_controller.rb:53
-#: ../../app/controllers/notes_controller.rb:47
+#: ../../app/controllers/notes_controller.rb:48
#: ../../app/controllers/org_admin/departments_controller.rb:26
#: ../../app/controllers/org_admin/phases_controller.rb:121
#: ../../app/controllers/org_admin/questions_controller.rb:94
@@ -348,7 +356,7 @@ msgstr "creado"
#: ../../app/controllers/guidance_groups_controller.rb:34
#: ../../app/controllers/guidances_controller.rb:55
-#: ../../app/controllers/notes_controller.rb:66
+#: ../../app/controllers/notes_controller.rb:67
#: ../../app/controllers/org_admin/departments_controller.rb:30
#: ../../app/controllers/org_admin/phases_controller.rb:123
#: ../../app/controllers/org_admin/questions_controller.rb:96
@@ -391,7 +399,7 @@ msgstr "Despublicar"
#: ../../app/controllers/org_admin/question_options_controller.rb:24
#: ../../app/controllers/org_admin/questions_controller.rb:197
#: ../../app/controllers/org_admin/sections_controller.rb:128
-#: ../../app/controllers/plans_controller.rb:342
+#: ../../app/controllers/plans_controller.rb:343
#: ../../app/controllers/super_admin/api_clients_controller.rb:81
#: ../../app/controllers/super_admin/notifications_controller.rb:85
#: ../../app/controllers/super_admin/themes_controller.rb:51
@@ -405,7 +413,7 @@ msgstr "Suprimido"
#: ../../app/controllers/org_admin/question_options_controller.rb:26
#: ../../app/controllers/org_admin/questions_controller.rb:199
#: ../../app/controllers/org_admin/sections_controller.rb:130
-#: ../../app/controllers/plans_controller.rb:347
+#: ../../app/controllers/plans_controller.rb:348
#: ../../app/controllers/super_admin/api_clients_controller.rb:84
#: ../../app/controllers/super_admin/notifications_controller.rb:88
#: ../../app/controllers/super_admin/themes_controller.rb:54
@@ -446,19 +454,19 @@ msgstr "No se puede crear una nueva versión de esta plantilla.
"
#: ../../app/controllers/org_admin/phases_controller.rb:147
#: ../../app/controllers/org_admin/questions_controller.rb:166
#: ../../app/controllers/org_admin/users_controller.rb:30
-#: ../../app/controllers/plans_controller.rb:416
+#: ../../app/controllers/plans_controller.rb:417
#: ../../app/controllers/super_admin/api_clients_controller.rb:68
#: ../../app/controllers/super_admin/notifications_controller.rb:52
#: ../../app/controllers/super_admin/themes_controller.rb:39
#: ../../app/controllers/super_admin/users_controller.rb:54
-#: ../../app/controllers/users_controller.rb:108
+#: ../../app/controllers/users_controller.rb:109
msgid "updated"
msgstr "Actualizado"
#: ../../app/controllers/org_admin/phases_controller.rb:149
#: ../../app/controllers/org_admin/questions_controller.rb:169
#: ../../app/controllers/org_admin/users_controller.rb:32
-#: ../../app/controllers/plans_controller.rb:419
+#: ../../app/controllers/plans_controller.rb:420
#: ../../app/controllers/super_admin/api_clients_controller.rb:70
#: ../../app/controllers/super_admin/notifications_controller.rb:55
#: ../../app/controllers/super_admin/themes_controller.rb:41
@@ -550,7 +558,7 @@ msgid "Unable to delete this version of the template."
msgstr "No se puede eliminar esta versión de la plantilla."
#: ../../app/controllers/org_admin/template_copies_controller.rb:20
-#: ../../app/controllers/plans_controller.rb:395
+#: ../../app/controllers/plans_controller.rb:396
msgid "copy"
msgstr "Dupdo"
@@ -559,11 +567,11 @@ msgstr "Dupdo"
msgid "That template is no longer customizable."
msgstr "Esa plantilla ya no es personalizable."
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:21
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:22
msgid "Unable to customize that template."
msgstr "No se puede personalizar esa plantilla."
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:24
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:25
msgid "That template is not customizable."
msgstr "Esa plantilla no es personalizable."
@@ -655,11 +663,11 @@ msgstr "Este plan se basa en el"
msgid "template with customisations by the"
msgstr "plantilla con personalizaciones por el"
-#: ../../app/controllers/plans_controller.rb:393
+#: ../../app/controllers/plans_controller.rb:394
msgid "copied"
msgstr "copiado"
-#: ../../app/controllers/plans_controller.rb:424
+#: ../../app/controllers/plans_controller.rb:425
msgid ""
"Unable to change the plan's status since it is needed at least %{percentage} p"
"ercentage responded"
@@ -667,23 +675,23 @@ msgstr ""
"No se puede cambiar el estado del plan ya que se necesita al menos el porcenta"
"je %{percentage} respondido"
-#: ../../app/controllers/plans_controller.rb:430
+#: ../../app/controllers/plans_controller.rb:431
msgid "Unable to find plan id %{plan_id}"
msgstr "No se puede encontrar la identificación del plan %{plan_id}"
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is now a test."
msgstr "Tu proyecto es ahora una prueba."
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is no longer a test."
msgstr "Tu proyecto ya no es una prueba."
-#: ../../app/controllers/plans_controller.rb:449
+#: ../../app/controllers/plans_controller.rb:450
msgid "Unable to change the plan's test status"
msgstr "No se puede cambiar el estado de prueba del plan"
-#: ../../app/controllers/plans_controller.rb:462
+#: ../../app/controllers/plans_controller.rb:463
msgid "There is no plan associated with id %{s"
msgstr "No hay plan asociado con id %{ s"
@@ -781,7 +789,7 @@ msgstr "La contraseña y la confirmación deben coincidir"
msgid "research output not found"
msgstr "resultado de la investigación no encontrado"
-#: ../../app/controllers/roles_controller.rb:26
+#: ../../app/controllers/roles_controller.rb:27
msgid ""
"Cannot share plan with %{email} since that email matches\n"
" with the owner of the plan."
@@ -960,27 +968,27 @@ msgstr "Su cuenta se ha vinculado con éxito a %{scheme}."
msgid "Unable to link your account to %{scheme}."
msgstr "No se puede vincular su cuenta a %{scheme}."
-#: ../../app/controllers/users_controller.rb:149
+#: ../../app/controllers/users_controller.rb:150
msgid "Successfully %{action} %{username}'s account."
msgstr "Con éxito la cuenta de %{action} %{username}."
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "activated"
msgstr "activado"
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "deactivated"
msgstr "Desactivado"
-#: ../../app/controllers/users_controller.rb:156
+#: ../../app/controllers/users_controller.rb:157
msgid "Unable to %{action} %{username}"
msgstr "No se puede %{action} %{username}"
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "activate"
msgstr "Activar"
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "deactivate"
msgstr "Desactivar"
@@ -1273,50 +1281,50 @@ msgstr "Últimos 9 meses"
msgid "Last 12 months"
msgstr "Últimos 12 meses"
-#: ../../app/mailers/user_mailer.rb:17
+#: ../../app/mailers/user_mailer.rb:18
#: ../../app/views/devise/mailer/invitation_instructions.html.erb:5
#: ../../app/views/devise/mailer/reset_password_instructions.html.erb:5
#: ../../app/views/user_mailer/_email_signature.html.erb:2
msgid "Query or feedback related to %{tool_name}"
msgstr "Consulta o feedback relacionado con %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:25
+#: ../../app/mailers/user_mailer.rb:26
msgid "Welcome to %{tool_name}"
msgstr "Bienvenido a %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:62
+#: ../../app/mailers/user_mailer.rb:63
msgid "A Data Management Plan in %{tool_name} has been shared with you"
msgstr "Se ha compartido con usted un Plan de gestión de datos en %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:79
+#: ../../app/mailers/user_mailer.rb:80
msgid "Changed permissions on a Data Management Plan in %{tool_name}"
msgstr "Cambios de permisos en un plan de gestión de datos en %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:94
+#: ../../app/mailers/user_mailer.rb:95
msgid "Permissions removed on a DMP in %{tool_name}"
msgstr "Permisos eliminados en un DMP en %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:112
+#: ../../app/mailers/user_mailer.rb:113
msgid "%{user_name} has requested feedback on a %{tool_name} plan"
msgstr "%{user_name} ha solicitado comentarios sobre un plan %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:135
+#: ../../app/mailers/user_mailer.rb:136
msgid "%{tool_name}: Expert feedback has been provided for %{plan_title}"
msgstr "%{tool_name}: Se han proporcionado comentarios de expertos para %{plan_title}"
-#: ../../app/mailers/user_mailer.rb:153
+#: ../../app/mailers/user_mailer.rb:154
msgid "DMP Visibility Changed: %{plan_title}"
msgstr "Se modificó la visibilidad de DMP: %{plan_title}"
-#: ../../app/mailers/user_mailer.rb:182
+#: ../../app/mailers/user_mailer.rb:183
msgid "%{tool_name}: A new comment was added to %{plan_title}"
msgstr "%{tool_name}: Se agregó un nuevo comentario a %{plan_title}"
-#: ../../app/mailers/user_mailer.rb:198
+#: ../../app/mailers/user_mailer.rb:199
msgid "Administrator privileges granted in %{tool_name}"
msgstr "Privilegios de administrador otorgados en %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:216
+#: ../../app/mailers/user_mailer.rb:217
msgid "%{tool_name} API changes"
msgstr "%{tool_name} Cambios de API"
@@ -1556,15 +1564,15 @@ msgstr ""
msgid "already assigned a value"
msgstr "ya asignado un valor"
-#: ../../app/models/org.rb:46
+#: ../../app/models/org.rb:47
msgid "Feedback email message"
msgstr "Mensaje de correo electrónico de comentarios"
-#: ../../app/models/org.rb:123
+#: ../../app/models/org.rb:124
msgid "must be one of the following formats: jpeg, jpg, png, gif, bmp"
msgstr "debe ser uno de los siguientes formatos: jpeg, jpg, png, gif, bmp"
-#: ../../app/models/org.rb:128
+#: ../../app/models/org.rb:129
msgid "can't be larger than 500KB"
msgstr "no puede ser más grande que 500KB"
@@ -1690,7 +1698,7 @@ msgstr "No se puede publicar una plantilla sin preguntas en una sección."
msgid "Conditions in the template refer backwards"
msgstr "Las condiciones en la plantilla se refieren al revés"
-#: ../../app/models/user.rb:380
+#: ../../app/models/user.rb:386
msgid "A Data Management Plan in %{application_name} has been shared with you"
msgstr "Se ha compartido un plan de gestión de datos en %{application_name} con usted"
@@ -2120,7 +2128,7 @@ msgstr ""
#: ../../app/views/paginable/templates/_organisational.html.erb:87
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:29
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:36
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
#: ../../app/views/static_pages/about_us.html.erb:22
#: ../../app/views/static_pages/about_us.html.erb:29
#: ../../app/views/static_pages/termsuse.html.erb:46
@@ -4633,7 +4641,7 @@ msgstr "Comentarios y orientación"
msgid "Instructions"
msgstr "Instrucciones"
-#: ../../app/views/plans/_download_form.html.erb:6
+#: ../../app/views/plans/_download_form.html.erb:5
msgid "Format"
msgstr "Formato"
@@ -4641,71 +4649,71 @@ msgstr "Formato"
msgid "Download settings"
msgstr "Descargar ajustes"
-#: ../../app/views/plans/_download_form.html.erb:19
-msgid "Select phase to download"
-msgstr "Seleccione la fase para descargar"
-
-#: ../../app/views/plans/_download_form.html.erb:26
+#: ../../app/views/plans/_download_form.html.erb:21
msgid "Optional plan components"
msgstr "Componentes opcionales del plan"
-#: ../../app/views/plans/_download_form.html.erb:30
+#: ../../app/views/plans/_download_form.html.erb:25
msgid "project details coversheet"
msgstr "detalles del proyecto portada"
-#: ../../app/views/plans/_download_form.html.erb:36
+#: ../../app/views/plans/_download_form.html.erb:31
msgid "question text and section headings"
msgstr "texto de la pregunta y encabezados de sección"
-#: ../../app/views/plans/_download_form.html.erb:42
+#: ../../app/views/plans/_download_form.html.erb:37
msgid "unanswered questions"
msgstr "preguntas sin respuesta"
-#: ../../app/views/plans/_download_form.html.erb:49
+#: ../../app/views/plans/_download_form.html.erb:44
msgid "research outputs"
msgstr "resultados de la investigación"
-#: ../../app/views/plans/_download_form.html.erb:57
+#: ../../app/views/plans/_download_form.html.erb:52
msgid "supplementary section(s) not requested by funding organisation"
msgstr "Secciones complementarias no solicitadas por la organización financiadora"
-#: ../../app/views/plans/_download_form.html.erb:65
+#: ../../app/views/plans/_download_form.html.erb:61
+msgid "Select phase to download"
+msgstr "Seleccione la fase para descargar"
+
+#: ../../app/views/plans/_download_form.html.erb:70
msgid "PDF formatting"
msgstr "Formato PDF"
-#: ../../app/views/plans/_download_form.html.erb:68
+#: ../../app/views/plans/_download_form.html.erb:73
msgid "Font"
msgstr "Fuente"
-#: ../../app/views/plans/_download_form.html.erb:71
+#: ../../app/views/plans/_download_form.html.erb:76
msgid "Margin (mm)"
msgstr "Margen (mm)"
-#: ../../app/views/plans/_download_form.html.erb:76
+#: ../../app/views/plans/_download_form.html.erb:81
msgid "Face"
msgstr "Estilo"
-#: ../../app/views/plans/_download_form.html.erb:84
+#: ../../app/views/plans/_download_form.html.erb:89
msgid "Size"
msgstr "Tamaño"
-#: ../../app/views/plans/_download_form.html.erb:92
+#: ../../app/views/plans/_download_form.html.erb:96
msgid "Top"
msgstr "Superior"
-#: ../../app/views/plans/_download_form.html.erb:101
+#: ../../app/views/plans/_download_form.html.erb:105
msgid "Bottom"
msgstr "Inferior"
-#: ../../app/views/plans/_download_form.html.erb:110
+#: ../../app/views/plans/_download_form.html.erb:114
msgid "Left"
msgstr "Izquierdo"
-#: ../../app/views/plans/_download_form.html.erb:119
+#: ../../app/views/plans/_download_form.html.erb:123
msgid "Right"
msgstr "Derecho"
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
msgid ""
"Download Plan (new window)%{open_in_new_window_text}"
diff --git a/config/locale/fi/LC_MESSAGES/app.mo b/config/locale/fi/LC_MESSAGES/app.mo
index bf7f0bf1d1..1e5af65c72 100644
Binary files a/config/locale/fi/LC_MESSAGES/app.mo and b/config/locale/fi/LC_MESSAGES/app.mo differ
diff --git a/config/locale/fi/app.po b/config/locale/fi/app.po
index da6ecaa6c3..b2c9d08948 100644
--- a/config/locale/fi/app.po
+++ b/config/locale/fi/app.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: roadmap_upstream 1.0\n"
"Report-Msgid-Bugs-To: contact@translation.io\n"
-"POT-Creation-Date: 2025-04-10 13:28-0600\n"
-"PO-Revision-Date: 2025-04-10 21:28+0200\n"
+"POT-Creation-Date: 2025-12-23 08:33-0700\n"
+"PO-Revision-Date: 2025-12-23 15:33+0000\n"
"Last-Translator: FULL NAME \n"
"Language-Team: Finnish\n"
"Language: fi\n"
@@ -129,87 +129,95 @@ msgstr "Virheellinen JSON"
msgid "No Plans found"
msgstr "Suunnitelmia ei löytynyt"
-#: ../../app/controllers/application_controller.rb:36
+#: ../../app/controllers/api/v2/base_api_controller.rb:72
+msgid "There was a problem in the server."
+msgstr "Palvelimella oli ongelma."
+
+#: ../../app/controllers/api/v2/base_api_controller.rb:78
+msgid "The client is not authorized to perform this action."
+msgstr "Asiakkaalla ei ole oikeutta suorittaa tätä toimintoa."
+
+#: ../../app/controllers/application_controller.rb:37
msgid "You are not authorized to perform this action."
msgstr "Sinulla ei ole oikeuksia suorittaa tätä toimintoa."
-#: ../../app/controllers/application_controller.rb:40
+#: ../../app/controllers/application_controller.rb:41
msgid "You need to sign in or sign up before continuing."
msgstr "Kirjaudu sisään tai rekisteröidy jatkaaksesi."
-#: ../../app/controllers/application_controller.rb:108
+#: ../../app/controllers/application_controller.rb:115
msgid "Unable to %{action} the %{object}. %{errors}"
msgstr "Ei voida %{action} %{object}. %{errors}"
-#: ../../app/controllers/application_controller.rb:114
+#: ../../app/controllers/application_controller.rb:121
msgid "Successfully %{action} the %{object}."
msgstr "%{object}:n %{action} onnistui."
-#: ../../app/controllers/application_controller.rb:127
+#: ../../app/controllers/application_controller.rb:134
msgid "API client"
msgstr "API-asiakas"
-#: ../../app/controllers/application_controller.rb:128
+#: ../../app/controllers/application_controller.rb:135
msgid "plan"
msgstr "suunnitelma"
-#: ../../app/controllers/application_controller.rb:129
+#: ../../app/controllers/application_controller.rb:136
msgid "guidance group"
msgstr "ohjeryhmä"
-#: ../../app/controllers/application_controller.rb:130
+#: ../../app/controllers/application_controller.rb:137
msgid "comment"
msgstr "kommentti"
-#: ../../app/controllers/application_controller.rb:131
+#: ../../app/controllers/application_controller.rb:138
msgid "organisation"
msgstr "organisaatio"
-#: ../../app/controllers/application_controller.rb:132
+#: ../../app/controllers/application_controller.rb:139
msgid "permission"
msgstr "käyttöoikeus"
-#: ../../app/controllers/application_controller.rb:133
+#: ../../app/controllers/application_controller.rb:140
msgid "preferences"
msgstr "asetukset"
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "profile"
msgstr "käyttäjätiedot"
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "user"
msgstr "käyttäjä"
-#: ../../app/controllers/application_controller.rb:135
+#: ../../app/controllers/application_controller.rb:142
msgid "question option"
msgstr "kysymysvaihtoehto"
-#: ../../app/controllers/application_controller.rb:181
+#: ../../app/controllers/application_controller.rb:188
msgid "Record Not Found"
msgstr "Levyä ei löydy"
-#: ../../app/controllers/concerns/paginable.rb:45
+#: ../../app/controllers/concerns/paginable.rb:46
msgid "scope should be an ActiveRecord::Relation object"
msgstr "kohteen pitäisi olla ActiveRecord::Relation object"
-#: ../../app/controllers/concerns/paginable.rb:47
+#: ../../app/controllers/concerns/paginable.rb:48
msgid "path_params should be a Hash object"
msgstr "path_params pitäisi olla Hash object"
-#: ../../app/controllers/concerns/paginable.rb:48
+#: ../../app/controllers/concerns/paginable.rb:49
msgid "query_params should be a Hash object"
msgstr "query_params pitäisi olla Hash object"
-#: ../../app/controllers/concerns/paginable.rb:49
+#: ../../app/controllers/concerns/paginable.rb:50
msgid "locals should be a Hash object"
msgstr "paikalliset pitäisi olla Hash objekti"
-#: ../../app/controllers/concerns/paginable.rb:70
+#: ../../app/controllers/concerns/paginable.rb:71
msgid "Restricted access to View All the records"
msgstr "Kaikkien tietojen tarkastelu on rajoitettu"
-#: ../../app/controllers/concerns/paginable.rb:183
+#: ../../app/controllers/concerns/paginable.rb:184
msgid "Sort by %{sort_field}"
msgstr "Järjestä %{sort_field}"
@@ -250,77 +258,77 @@ msgstr "Sähköpostin lähettäminen onnistui."
msgid "Unable to submit your request"
msgstr "Pyyntösi ei onnistu"
-#: ../../app/controllers/contributors_controller.rb:40
-#: ../../app/controllers/contributors_controller.rb:56
+#: ../../app/controllers/contributors_controller.rb:41
+#: ../../app/controllers/contributors_controller.rb:57
#: ../../app/controllers/research_outputs_controller.rb:42
msgid "add"
msgstr "lisätä"
-#: ../../app/controllers/contributors_controller.rb:54
+#: ../../app/controllers/contributors_controller.rb:55
#: ../../app/controllers/research_outputs_controller.rb:40
msgid "added"
msgstr "lisä-"
-#: ../../app/controllers/contributors_controller.rb:72
+#: ../../app/controllers/contributors_controller.rb:73
#: ../../app/controllers/guidance_groups_controller.rb:55
#: ../../app/controllers/guidances_controller.rb:75
-#: ../../app/controllers/notes_controller.rb:88
+#: ../../app/controllers/notes_controller.rb:89
#: ../../app/controllers/org_admin/departments_controller.rb:50
#: ../../app/controllers/org_admin/sections_controller.rb:103
#: ../../app/controllers/org_admin/templates_controller.rb:210
#: ../../app/controllers/orgs_controller.rb:92
-#: ../../app/controllers/plans_controller.rb:280
-#: ../../app/controllers/plans_controller.rb:283
+#: ../../app/controllers/plans_controller.rb:281
+#: ../../app/controllers/plans_controller.rb:284
#: ../../app/controllers/registrations_controller.rb:249
#: ../../app/controllers/registrations_controller.rb:253
#: ../../app/controllers/registrations_controller.rb:280
#: ../../app/controllers/registrations_controller.rb:284
#: ../../app/controllers/research_outputs_controller.rb:60
-#: ../../app/controllers/users_controller.rb:103
-#: ../../app/controllers/users_controller.rb:131
+#: ../../app/controllers/users_controller.rb:104
+#: ../../app/controllers/users_controller.rb:132
msgid "saved"
msgstr "tallennettu"
-#: ../../app/controllers/contributors_controller.rb:74
+#: ../../app/controllers/contributors_controller.rb:75
#: ../../app/controllers/guidance_groups_controller.rb:57
#: ../../app/controllers/guidances_controller.rb:77
-#: ../../app/controllers/notes_controller.rb:106
+#: ../../app/controllers/notes_controller.rb:107
#: ../../app/controllers/org_admin/departments_controller.rb:52
#: ../../app/controllers/org_admin/sections_controller.rb:105
#: ../../app/controllers/org_admin/templates_controller.rb:215
#: ../../app/controllers/orgs_controller.rb:94
-#: ../../app/controllers/plans_controller.rb:289
-#: ../../app/controllers/plans_controller.rb:292
-#: ../../app/controllers/plans_controller.rb:296
-#: ../../app/controllers/plans_controller.rb:299
+#: ../../app/controllers/plans_controller.rb:290
+#: ../../app/controllers/plans_controller.rb:293
+#: ../../app/controllers/plans_controller.rb:297
+#: ../../app/controllers/plans_controller.rb:300
#: ../../app/controllers/registrations_controller.rb:256
#: ../../app/controllers/registrations_controller.rb:287
#: ../../app/controllers/research_outputs_controller.rb:63
msgid "save"
msgstr "tallenna"
-#: ../../app/controllers/contributors_controller.rb:83
-#: ../../app/controllers/notes_controller.rb:130
+#: ../../app/controllers/contributors_controller.rb:84
+#: ../../app/controllers/notes_controller.rb:131
#: ../../app/controllers/org_admin/templates_controller.rb:243
#: ../../app/controllers/research_outputs_controller.rb:74
#: ../../app/controllers/super_admin/orgs_controller.rb:94
msgid "removed"
msgstr "poistettu"
-#: ../../app/controllers/contributors_controller.rb:86
-#: ../../app/controllers/notes_controller.rb:148
+#: ../../app/controllers/contributors_controller.rb:87
+#: ../../app/controllers/notes_controller.rb:149
#: ../../app/controllers/org_admin/templates_controller.rb:245
#: ../../app/controllers/research_outputs_controller.rb:77
#: ../../app/controllers/super_admin/orgs_controller.rb:97
msgid "remove"
msgstr "poista"
-#: ../../app/controllers/contributors_controller.rb:160
+#: ../../app/controllers/contributors_controller.rb:161
#: ../../app/controllers/research_outputs_controller.rb:208
msgid "plan not found"
msgstr "Suunnitelmaa ei löytynyt"
-#: ../../app/controllers/contributors_controller.rb:168
+#: ../../app/controllers/contributors_controller.rb:169
msgid "contributor not found"
msgstr "osallistujaa ei löytynyt"
@@ -334,7 +342,7 @@ msgstr "Tapahtui virhe, kun pyysit palautetta tälle suunnitelmalle."
#: ../../app/controllers/guidance_groups_controller.rb:31
#: ../../app/controllers/guidances_controller.rb:53
-#: ../../app/controllers/notes_controller.rb:47
+#: ../../app/controllers/notes_controller.rb:48
#: ../../app/controllers/org_admin/departments_controller.rb:26
#: ../../app/controllers/org_admin/phases_controller.rb:121
#: ../../app/controllers/org_admin/questions_controller.rb:94
@@ -350,7 +358,7 @@ msgstr "luominen"
#: ../../app/controllers/guidance_groups_controller.rb:34
#: ../../app/controllers/guidances_controller.rb:55
-#: ../../app/controllers/notes_controller.rb:66
+#: ../../app/controllers/notes_controller.rb:67
#: ../../app/controllers/org_admin/departments_controller.rb:30
#: ../../app/controllers/org_admin/phases_controller.rb:123
#: ../../app/controllers/org_admin/questions_controller.rb:96
@@ -389,7 +397,7 @@ msgstr "piilota"
#: ../../app/controllers/org_admin/question_options_controller.rb:24
#: ../../app/controllers/org_admin/questions_controller.rb:197
#: ../../app/controllers/org_admin/sections_controller.rb:128
-#: ../../app/controllers/plans_controller.rb:342
+#: ../../app/controllers/plans_controller.rb:343
#: ../../app/controllers/super_admin/api_clients_controller.rb:81
#: ../../app/controllers/super_admin/notifications_controller.rb:85
#: ../../app/controllers/super_admin/themes_controller.rb:51
@@ -403,7 +411,7 @@ msgstr "poistettu"
#: ../../app/controllers/org_admin/question_options_controller.rb:26
#: ../../app/controllers/org_admin/questions_controller.rb:199
#: ../../app/controllers/org_admin/sections_controller.rb:130
-#: ../../app/controllers/plans_controller.rb:347
+#: ../../app/controllers/plans_controller.rb:348
#: ../../app/controllers/super_admin/api_clients_controller.rb:84
#: ../../app/controllers/super_admin/notifications_controller.rb:88
#: ../../app/controllers/super_admin/themes_controller.rb:54
@@ -446,19 +454,19 @@ msgstr "Tästä mallista ei voi luoda uutta versiota.
"
#: ../../app/controllers/org_admin/phases_controller.rb:147
#: ../../app/controllers/org_admin/questions_controller.rb:166
#: ../../app/controllers/org_admin/users_controller.rb:30
-#: ../../app/controllers/plans_controller.rb:416
+#: ../../app/controllers/plans_controller.rb:417
#: ../../app/controllers/super_admin/api_clients_controller.rb:68
#: ../../app/controllers/super_admin/notifications_controller.rb:52
#: ../../app/controllers/super_admin/themes_controller.rb:39
#: ../../app/controllers/super_admin/users_controller.rb:54
-#: ../../app/controllers/users_controller.rb:108
+#: ../../app/controllers/users_controller.rb:109
msgid "updated"
msgstr "päivitetty"
#: ../../app/controllers/org_admin/phases_controller.rb:149
#: ../../app/controllers/org_admin/questions_controller.rb:169
#: ../../app/controllers/org_admin/users_controller.rb:32
-#: ../../app/controllers/plans_controller.rb:419
+#: ../../app/controllers/plans_controller.rb:420
#: ../../app/controllers/super_admin/api_clients_controller.rb:70
#: ../../app/controllers/super_admin/notifications_controller.rb:55
#: ../../app/controllers/super_admin/themes_controller.rb:41
@@ -548,7 +556,7 @@ msgid "Unable to delete this version of the template."
msgstr "Tätä mallin versiota ei voi poistaa."
#: ../../app/controllers/org_admin/template_copies_controller.rb:20
-#: ../../app/controllers/plans_controller.rb:395
+#: ../../app/controllers/plans_controller.rb:396
msgid "copy"
msgstr "kopio"
@@ -557,11 +565,11 @@ msgstr "kopio"
msgid "That template is no longer customizable."
msgstr "Suunnitelmapohjaa ei voi enää mukauttaa."
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:21
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:22
msgid "Unable to customize that template."
msgstr "Suunnitelmapohjan mukauttaminen ei onnistu."
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:24
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:25
msgid "That template is not customizable."
msgstr "Suunnitelmapohjaa ei voi mukauttaa."
@@ -653,11 +661,11 @@ msgstr "Suunnitelma perustuu"
msgid "template with customisations by the"
msgstr "malli asiakassuhteiden mukauttamisella"
-#: ../../app/controllers/plans_controller.rb:393
+#: ../../app/controllers/plans_controller.rb:394
msgid "copied"
msgstr "kopionti"
-#: ../../app/controllers/plans_controller.rb:424
+#: ../../app/controllers/plans_controller.rb:425
msgid ""
"Unable to change the plan's status since it is needed at least %{percentage} p"
"ercentage responded"
@@ -665,23 +673,23 @@ msgstr ""
"Suunnitelman tilan muuttaminen ei onnistunut, koska vähintään %{percentage}:a "
"vastauksista pitää olla vastattuna"
-#: ../../app/controllers/plans_controller.rb:430
+#: ../../app/controllers/plans_controller.rb:431
msgid "Unable to find plan id %{plan_id}"
msgstr "Suunnitelman tunnistetta %{plan_id} ei löydy"
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is now a test."
msgstr "Projektisi on nyt testimuodossa."
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is no longer a test."
msgstr "Projektisi ei ole enää testimuodossa."
-#: ../../app/controllers/plans_controller.rb:449
+#: ../../app/controllers/plans_controller.rb:450
msgid "Unable to change the plan's test status"
msgstr "Suunnitelman testistatuksen muuttaminen ei onnistu"
-#: ../../app/controllers/plans_controller.rb:462
+#: ../../app/controllers/plans_controller.rb:463
msgid "There is no plan associated with id %{s"
msgstr "Tunnukseen %{ ei liity suunnitelmaa s"
@@ -775,7 +783,7 @@ msgstr "Salasanan ja sen vahvistuksen on oltava samoja"
msgid "research output not found"
msgstr "tutkimustulosta ei löytynyt"
-#: ../../app/controllers/roles_controller.rb:26
+#: ../../app/controllers/roles_controller.rb:27
msgid ""
"Cannot share plan with %{email} since that email matches\n"
" with the owner of the plan."
@@ -950,27 +958,27 @@ msgstr "Tilisi liitettiin onnistuneesti %{scheme}:n."
msgid "Unable to link your account to %{scheme}."
msgstr "Tilisi liittäminen %{scheme}:hin ei onnistunut."
-#: ../../app/controllers/users_controller.rb:149
+#: ../../app/controllers/users_controller.rb:150
msgid "Successfully %{action} %{username}'s account."
msgstr "%{username}n tilin %{action} onnistui."
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "activated"
msgstr "aktivoitu"
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "deactivated"
msgstr "pois käytöstä"
-#: ../../app/controllers/users_controller.rb:156
+#: ../../app/controllers/users_controller.rb:157
msgid "Unable to %{action} %{username}"
msgstr "%{username}:n %{action} ei onnistunut"
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "activate"
msgstr "aktivoi"
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "deactivate"
msgstr "kytke pois päältä"
@@ -1262,52 +1270,52 @@ msgstr "Viimeiset 9 kuukautta"
msgid "Last 12 months"
msgstr "Viimeiset 12 kuukautta"
-#: ../../app/mailers/user_mailer.rb:17
+#: ../../app/mailers/user_mailer.rb:18
#: ../../app/views/devise/mailer/invitation_instructions.html.erb:5
#: ../../app/views/devise/mailer/reset_password_instructions.html.erb:5
#: ../../app/views/user_mailer/_email_signature.html.erb:2
msgid "Query or feedback related to %{tool_name}"
msgstr "%{tool_name}:n liittyvä kysymys tai palaute"
-#: ../../app/mailers/user_mailer.rb:25
+#: ../../app/mailers/user_mailer.rb:26
msgid "Welcome to %{tool_name}"
msgstr "Tervetuloa %{tool_name}:n käyttäjäksi"
-#: ../../app/mailers/user_mailer.rb:62
+#: ../../app/mailers/user_mailer.rb:63
msgid "A Data Management Plan in %{tool_name} has been shared with you"
msgstr "Tiedonhallintasuunnitelma %{tool_name} -palvelussa on jaettu kanssasi"
-#: ../../app/mailers/user_mailer.rb:79
+#: ../../app/mailers/user_mailer.rb:80
msgid "Changed permissions on a Data Management Plan in %{tool_name}"
msgstr ""
"%{tool_name}:ssa olevan aineistonhallintasuunnitelman käyttöoikeuksia on muute"
"ttu"
-#: ../../app/mailers/user_mailer.rb:94
+#: ../../app/mailers/user_mailer.rb:95
msgid "Permissions removed on a DMP in %{tool_name}"
msgstr "DMP: ltä poistetut käyttöoikeudet %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:112
+#: ../../app/mailers/user_mailer.rb:113
msgid "%{user_name} has requested feedback on a %{tool_name} plan"
msgstr "%{user_name} on pyytänyt palautetta %{tool_name} -suunnitelmasta"
-#: ../../app/mailers/user_mailer.rb:135
+#: ../../app/mailers/user_mailer.rb:136
msgid "%{tool_name}: Expert feedback has been provided for %{plan_title}"
msgstr "%{tool_name}: %{plan_title}: lle on annettu asiantuntijapalautetta"
-#: ../../app/mailers/user_mailer.rb:153
+#: ../../app/mailers/user_mailer.rb:154
msgid "DMP Visibility Changed: %{plan_title}"
msgstr "Suunnitelman näkyvyys on muuttunut: %{plan_title}"
-#: ../../app/mailers/user_mailer.rb:182
+#: ../../app/mailers/user_mailer.rb:183
msgid "%{tool_name}: A new comment was added to %{plan_title}"
msgstr "%{tool_name}: Uusi kommentti lisättiin suunnitelmaasi %{plan_title}"
-#: ../../app/mailers/user_mailer.rb:198
+#: ../../app/mailers/user_mailer.rb:199
msgid "Administrator privileges granted in %{tool_name}"
msgstr "Minulle myönnetyt ylläpito-oikeudet %{tool_name}:ssa"
-#: ../../app/mailers/user_mailer.rb:216
+#: ../../app/mailers/user_mailer.rb:217
msgid "%{tool_name} API changes"
msgstr "%{tool_name} API-muutokset"
@@ -1543,15 +1551,15 @@ msgstr "Kysymykseen ei vastattu.\\n"
msgid "already assigned a value"
msgstr "jo määritetty arvo"
-#: ../../app/models/org.rb:46
+#: ../../app/models/org.rb:47
msgid "Feedback email message"
msgstr "Palautteen sähköpostiviesti"
-#: ../../app/models/org.rb:123
+#: ../../app/models/org.rb:124
msgid "must be one of the following formats: jpeg, jpg, png, gif, bmp"
msgstr "täytyy olla yksi seuraavista tiedostomuodoista: jpeg, jpg, png, gif, bmp"
-#: ../../app/models/org.rb:128
+#: ../../app/models/org.rb:129
msgid "can't be larger than 500KB"
msgstr "ei voi olla suurempi kuin 500KB"
@@ -1675,7 +1683,7 @@ msgstr "Et voi julkaista mallipohjaa ilman kysymyksiä."
msgid "Conditions in the template refer backwards"
msgstr "Mallin ehdot viittaavat taaksepäin"
-#: ../../app/models/user.rb:380
+#: ../../app/models/user.rb:386
msgid "A Data Management Plan in %{application_name} has been shared with you"
msgstr ""
"%{application_name}lla kirjoitettu aineistonhallintasuunnitelma on jaettu kans"
@@ -2107,7 +2115,7 @@ msgstr ""
#: ../../app/views/paginable/templates/_organisational.html.erb:87
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:29
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:36
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
#: ../../app/views/static_pages/about_us.html.erb:22
#: ../../app/views/static_pages/about_us.html.erb:29
#: ../../app/views/static_pages/termsuse.html.erb:46
@@ -4606,7 +4614,7 @@ msgstr "Kommentit ja ohjeet"
msgid "Instructions"
msgstr "Ohjeet"
-#: ../../app/views/plans/_download_form.html.erb:6
+#: ../../app/views/plans/_download_form.html.erb:5
msgid "Format"
msgstr "Tiedostomuoto"
@@ -4614,72 +4622,72 @@ msgstr "Tiedostomuoto"
msgid "Download settings"
msgstr "Asetukset"
-#: ../../app/views/plans/_download_form.html.erb:19
-msgid "Select phase to download"
-msgstr "Valitse vaihe ladattavaksi"
-
-#: ../../app/views/plans/_download_form.html.erb:26
+#: ../../app/views/plans/_download_form.html.erb:21
msgid "Optional plan components"
msgstr ""
"Valinnaiset suunnitelman osat\n"
-#: ../../app/views/plans/_download_form.html.erb:30
+#: ../../app/views/plans/_download_form.html.erb:25
msgid "project details coversheet"
msgstr "Projektin tiedot"
-#: ../../app/views/plans/_download_form.html.erb:36
+#: ../../app/views/plans/_download_form.html.erb:31
msgid "question text and section headings"
msgstr "Kysymyksen teksti ja osioiden otsikot"
-#: ../../app/views/plans/_download_form.html.erb:42
+#: ../../app/views/plans/_download_form.html.erb:37
msgid "unanswered questions"
msgstr "Vastaamattomat kysymykset"
-#: ../../app/views/plans/_download_form.html.erb:49
+#: ../../app/views/plans/_download_form.html.erb:44
msgid "research outputs"
msgstr "tutkimustuloksista"
-#: ../../app/views/plans/_download_form.html.erb:57
+#: ../../app/views/plans/_download_form.html.erb:52
msgid "supplementary section(s) not requested by funding organisation"
msgstr "lisäosiot, joita rahoittajat eivät edellytä"
-#: ../../app/views/plans/_download_form.html.erb:65
+#: ../../app/views/plans/_download_form.html.erb:61
+msgid "Select phase to download"
+msgstr "Valitse vaihe ladattavaksi"
+
+#: ../../app/views/plans/_download_form.html.erb:70
msgid "PDF formatting"
msgstr "PDF:n muotoilu"
-#: ../../app/views/plans/_download_form.html.erb:68
+#: ../../app/views/plans/_download_form.html.erb:73
msgid "Font"
msgstr "Fontti"
-#: ../../app/views/plans/_download_form.html.erb:71
+#: ../../app/views/plans/_download_form.html.erb:76
msgid "Margin (mm)"
msgstr "Marginaali (mm)"
-#: ../../app/views/plans/_download_form.html.erb:76
+#: ../../app/views/plans/_download_form.html.erb:81
msgid "Face"
msgstr "Kirjasinlaji"
-#: ../../app/views/plans/_download_form.html.erb:84
+#: ../../app/views/plans/_download_form.html.erb:89
msgid "Size"
msgstr "Koko"
-#: ../../app/views/plans/_download_form.html.erb:92
+#: ../../app/views/plans/_download_form.html.erb:96
msgid "Top"
msgstr "Yläosa"
-#: ../../app/views/plans/_download_form.html.erb:101
+#: ../../app/views/plans/_download_form.html.erb:105
msgid "Bottom"
msgstr "Alaosa"
-#: ../../app/views/plans/_download_form.html.erb:110
+#: ../../app/views/plans/_download_form.html.erb:114
msgid "Left"
msgstr "Vasen"
-#: ../../app/views/plans/_download_form.html.erb:119
+#: ../../app/views/plans/_download_form.html.erb:123
msgid "Right"
msgstr "Oikea"
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
msgid ""
"Download Plan (new window)%{open_in_new_window_text}"
diff --git a/config/locale/fr_CA/LC_MESSAGES/app.mo b/config/locale/fr_CA/LC_MESSAGES/app.mo
index e5da555337..f31748c286 100644
Binary files a/config/locale/fr_CA/LC_MESSAGES/app.mo and b/config/locale/fr_CA/LC_MESSAGES/app.mo differ
diff --git a/config/locale/fr_CA/app.po b/config/locale/fr_CA/app.po
index dbea8d0b50..b71a5b7820 100644
--- a/config/locale/fr_CA/app.po
+++ b/config/locale/fr_CA/app.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: roadmap_upstream 1.0\n"
"Report-Msgid-Bugs-To: contact@translation.io\n"
-"POT-Creation-Date: 2025-04-10 13:28-0600\n"
-"PO-Revision-Date: 2025-04-10 21:28+0200\n"
+"POT-Creation-Date: 2025-12-23 08:33-0700\n"
+"PO-Revision-Date: 2025-12-23 15:33+0000\n"
"Last-Translator: FULL NAME \n"
"Language-Team: French\n"
"Language: fr_CA\n"
@@ -127,87 +127,95 @@ msgstr "Format JSON invalide"
msgid "No Plans found"
msgstr "Aucun plan n’a été trouvé"
-#: ../../app/controllers/application_controller.rb:36
+#: ../../app/controllers/api/v2/base_api_controller.rb:72
+msgid "There was a problem in the server."
+msgstr ""
+
+#: ../../app/controllers/api/v2/base_api_controller.rb:78
+msgid "The client is not authorized to perform this action."
+msgstr ""
+
+#: ../../app/controllers/application_controller.rb:37
msgid "You are not authorized to perform this action."
msgstr "Vous n’êtes pas autorisé à effectuer cette action."
-#: ../../app/controllers/application_controller.rb:40
+#: ../../app/controllers/application_controller.rb:41
msgid "You need to sign in or sign up before continuing."
msgstr "Vous devez vous connecter ou vous inscrire pour continuer."
-#: ../../app/controllers/application_controller.rb:108
+#: ../../app/controllers/application_controller.rb:115
msgid "Unable to %{action} the %{object}. %{errors}"
msgstr ""
-#: ../../app/controllers/application_controller.rb:114
+#: ../../app/controllers/application_controller.rb:121
msgid "Successfully %{action} the %{object}."
msgstr "La mesure %{action} pour %{object} a été effectuée avec succès."
-#: ../../app/controllers/application_controller.rb:127
+#: ../../app/controllers/application_controller.rb:134
msgid "API client"
msgstr "Client API"
-#: ../../app/controllers/application_controller.rb:128
+#: ../../app/controllers/application_controller.rb:135
msgid "plan"
msgstr "plan"
-#: ../../app/controllers/application_controller.rb:129
+#: ../../app/controllers/application_controller.rb:136
msgid "guidance group"
msgstr "groupe de directives"
-#: ../../app/controllers/application_controller.rb:130
+#: ../../app/controllers/application_controller.rb:137
msgid "comment"
msgstr "laisser un commentaire"
-#: ../../app/controllers/application_controller.rb:131
+#: ../../app/controllers/application_controller.rb:138
msgid "organisation"
msgstr "organisme"
-#: ../../app/controllers/application_controller.rb:132
+#: ../../app/controllers/application_controller.rb:139
msgid "permission"
msgstr "autorisation"
-#: ../../app/controllers/application_controller.rb:133
+#: ../../app/controllers/application_controller.rb:140
msgid "preferences"
msgstr "préférences"
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "profile"
msgstr "profil"
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "user"
msgstr "utilisateur(trice)"
-#: ../../app/controllers/application_controller.rb:135
+#: ../../app/controllers/application_controller.rb:142
msgid "question option"
msgstr "choix de questions"
-#: ../../app/controllers/application_controller.rb:181
+#: ../../app/controllers/application_controller.rb:188
msgid "Record Not Found"
msgstr ""
-#: ../../app/controllers/concerns/paginable.rb:45
+#: ../../app/controllers/concerns/paginable.rb:46
msgid "scope should be an ActiveRecord::Relation object"
msgstr "la portée doit être un objet ActiveRecord::Relation"
-#: ../../app/controllers/concerns/paginable.rb:47
+#: ../../app/controllers/concerns/paginable.rb:48
msgid "path_params should be a Hash object"
msgstr "path_params doit être un objet Hash"
-#: ../../app/controllers/concerns/paginable.rb:48
+#: ../../app/controllers/concerns/paginable.rb:49
msgid "query_params should be a Hash object"
msgstr "query_params doit constituer un objet Hash"
-#: ../../app/controllers/concerns/paginable.rb:49
+#: ../../app/controllers/concerns/paginable.rb:50
msgid "locals should be a Hash object"
msgstr "les valeurs locales doivent être un objet Hash"
-#: ../../app/controllers/concerns/paginable.rb:70
+#: ../../app/controllers/concerns/paginable.rb:71
msgid "Restricted access to View All the records"
msgstr "Accès restreint à Voir Tous les enregistrements"
-#: ../../app/controllers/concerns/paginable.rb:183
+#: ../../app/controllers/concerns/paginable.rb:184
msgid "Sort by %{sort_field}"
msgstr "Trier par %{sort_field}"
@@ -250,77 +258,77 @@ msgstr "Le courriel du contact a été envoyé avec succès."
msgid "Unable to submit your request"
msgstr "Il est impossible de soumettre votre demande"
-#: ../../app/controllers/contributors_controller.rb:40
-#: ../../app/controllers/contributors_controller.rb:56
+#: ../../app/controllers/contributors_controller.rb:41
+#: ../../app/controllers/contributors_controller.rb:57
#: ../../app/controllers/research_outputs_controller.rb:42
msgid "add"
msgstr "ajouter"
-#: ../../app/controllers/contributors_controller.rb:54
+#: ../../app/controllers/contributors_controller.rb:55
#: ../../app/controllers/research_outputs_controller.rb:40
msgid "added"
msgstr "ajouté"
-#: ../../app/controllers/contributors_controller.rb:72
+#: ../../app/controllers/contributors_controller.rb:73
#: ../../app/controllers/guidance_groups_controller.rb:55
#: ../../app/controllers/guidances_controller.rb:75
-#: ../../app/controllers/notes_controller.rb:88
+#: ../../app/controllers/notes_controller.rb:89
#: ../../app/controllers/org_admin/departments_controller.rb:50
#: ../../app/controllers/org_admin/sections_controller.rb:103
#: ../../app/controllers/org_admin/templates_controller.rb:210
#: ../../app/controllers/orgs_controller.rb:92
-#: ../../app/controllers/plans_controller.rb:280
-#: ../../app/controllers/plans_controller.rb:283
+#: ../../app/controllers/plans_controller.rb:281
+#: ../../app/controllers/plans_controller.rb:284
#: ../../app/controllers/registrations_controller.rb:249
#: ../../app/controllers/registrations_controller.rb:253
#: ../../app/controllers/registrations_controller.rb:280
#: ../../app/controllers/registrations_controller.rb:284
#: ../../app/controllers/research_outputs_controller.rb:60
-#: ../../app/controllers/users_controller.rb:103
-#: ../../app/controllers/users_controller.rb:131
+#: ../../app/controllers/users_controller.rb:104
+#: ../../app/controllers/users_controller.rb:132
msgid "saved"
msgstr "enregistré"
-#: ../../app/controllers/contributors_controller.rb:74
+#: ../../app/controllers/contributors_controller.rb:75
#: ../../app/controllers/guidance_groups_controller.rb:57
#: ../../app/controllers/guidances_controller.rb:77
-#: ../../app/controllers/notes_controller.rb:106
+#: ../../app/controllers/notes_controller.rb:107
#: ../../app/controllers/org_admin/departments_controller.rb:52
#: ../../app/controllers/org_admin/sections_controller.rb:105
#: ../../app/controllers/org_admin/templates_controller.rb:215
#: ../../app/controllers/orgs_controller.rb:94
-#: ../../app/controllers/plans_controller.rb:289
-#: ../../app/controllers/plans_controller.rb:292
-#: ../../app/controllers/plans_controller.rb:296
-#: ../../app/controllers/plans_controller.rb:299
+#: ../../app/controllers/plans_controller.rb:290
+#: ../../app/controllers/plans_controller.rb:293
+#: ../../app/controllers/plans_controller.rb:297
+#: ../../app/controllers/plans_controller.rb:300
#: ../../app/controllers/registrations_controller.rb:256
#: ../../app/controllers/registrations_controller.rb:287
#: ../../app/controllers/research_outputs_controller.rb:63
msgid "save"
msgstr "enregistrer"
-#: ../../app/controllers/contributors_controller.rb:83
-#: ../../app/controllers/notes_controller.rb:130
+#: ../../app/controllers/contributors_controller.rb:84
+#: ../../app/controllers/notes_controller.rb:131
#: ../../app/controllers/org_admin/templates_controller.rb:243
#: ../../app/controllers/research_outputs_controller.rb:74
#: ../../app/controllers/super_admin/orgs_controller.rb:94
msgid "removed"
msgstr "retiré"
-#: ../../app/controllers/contributors_controller.rb:86
-#: ../../app/controllers/notes_controller.rb:148
+#: ../../app/controllers/contributors_controller.rb:87
+#: ../../app/controllers/notes_controller.rb:149
#: ../../app/controllers/org_admin/templates_controller.rb:245
#: ../../app/controllers/research_outputs_controller.rb:77
#: ../../app/controllers/super_admin/orgs_controller.rb:97
msgid "remove"
msgstr "retirer"
-#: ../../app/controllers/contributors_controller.rb:160
+#: ../../app/controllers/contributors_controller.rb:161
#: ../../app/controllers/research_outputs_controller.rb:208
msgid "plan not found"
msgstr "plan non trouvé"
-#: ../../app/controllers/contributors_controller.rb:168
+#: ../../app/controllers/contributors_controller.rb:169
msgid "contributor not found"
msgstr "contributeur introuvable"
@@ -334,7 +342,7 @@ msgstr "Une erreur s’est produite lors de la demande de commentaires pour ce p
#: ../../app/controllers/guidance_groups_controller.rb:31
#: ../../app/controllers/guidances_controller.rb:53
-#: ../../app/controllers/notes_controller.rb:47
+#: ../../app/controllers/notes_controller.rb:48
#: ../../app/controllers/org_admin/departments_controller.rb:26
#: ../../app/controllers/org_admin/phases_controller.rb:121
#: ../../app/controllers/org_admin/questions_controller.rb:94
@@ -350,7 +358,7 @@ msgstr "créé"
#: ../../app/controllers/guidance_groups_controller.rb:34
#: ../../app/controllers/guidances_controller.rb:55
-#: ../../app/controllers/notes_controller.rb:66
+#: ../../app/controllers/notes_controller.rb:67
#: ../../app/controllers/org_admin/departments_controller.rb:30
#: ../../app/controllers/org_admin/phases_controller.rb:123
#: ../../app/controllers/org_admin/questions_controller.rb:96
@@ -393,7 +401,7 @@ msgstr "annuler la publication"
#: ../../app/controllers/org_admin/question_options_controller.rb:24
#: ../../app/controllers/org_admin/questions_controller.rb:197
#: ../../app/controllers/org_admin/sections_controller.rb:128
-#: ../../app/controllers/plans_controller.rb:342
+#: ../../app/controllers/plans_controller.rb:343
#: ../../app/controllers/super_admin/api_clients_controller.rb:81
#: ../../app/controllers/super_admin/notifications_controller.rb:85
#: ../../app/controllers/super_admin/themes_controller.rb:51
@@ -407,7 +415,7 @@ msgstr "supprimé"
#: ../../app/controllers/org_admin/question_options_controller.rb:26
#: ../../app/controllers/org_admin/questions_controller.rb:199
#: ../../app/controllers/org_admin/sections_controller.rb:130
-#: ../../app/controllers/plans_controller.rb:347
+#: ../../app/controllers/plans_controller.rb:348
#: ../../app/controllers/super_admin/api_clients_controller.rb:84
#: ../../app/controllers/super_admin/notifications_controller.rb:88
#: ../../app/controllers/super_admin/themes_controller.rb:54
@@ -454,19 +462,19 @@ msgstr ""
#: ../../app/controllers/org_admin/phases_controller.rb:147
#: ../../app/controllers/org_admin/questions_controller.rb:166
#: ../../app/controllers/org_admin/users_controller.rb:30
-#: ../../app/controllers/plans_controller.rb:416
+#: ../../app/controllers/plans_controller.rb:417
#: ../../app/controllers/super_admin/api_clients_controller.rb:68
#: ../../app/controllers/super_admin/notifications_controller.rb:52
#: ../../app/controllers/super_admin/themes_controller.rb:39
#: ../../app/controllers/super_admin/users_controller.rb:54
-#: ../../app/controllers/users_controller.rb:108
+#: ../../app/controllers/users_controller.rb:109
msgid "updated"
msgstr "mis à jour"
#: ../../app/controllers/org_admin/phases_controller.rb:149
#: ../../app/controllers/org_admin/questions_controller.rb:169
#: ../../app/controllers/org_admin/users_controller.rb:32
-#: ../../app/controllers/plans_controller.rb:419
+#: ../../app/controllers/plans_controller.rb:420
#: ../../app/controllers/super_admin/api_clients_controller.rb:70
#: ../../app/controllers/super_admin/notifications_controller.rb:55
#: ../../app/controllers/super_admin/themes_controller.rb:41
@@ -560,7 +568,7 @@ msgid "Unable to delete this version of the template."
msgstr ""
#: ../../app/controllers/org_admin/template_copies_controller.rb:20
-#: ../../app/controllers/plans_controller.rb:395
+#: ../../app/controllers/plans_controller.rb:396
msgid "copy"
msgstr "copier"
@@ -569,11 +577,11 @@ msgstr "copier"
msgid "That template is no longer customizable."
msgstr "Ce modèle n’est plus personnalisable."
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:21
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:22
msgid "Unable to customize that template."
msgstr "Il est impossible de personnaliser ce modèle."
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:24
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:25
msgid "That template is not customizable."
msgstr "Ce modèle n’est pas personnalisable."
@@ -665,11 +673,11 @@ msgstr "Ce plan est fondé sur "
msgid "template with customisations by the"
msgstr "modèle avec des personnalisations par le"
-#: ../../app/controllers/plans_controller.rb:393
+#: ../../app/controllers/plans_controller.rb:394
msgid "copied"
msgstr "copié"
-#: ../../app/controllers/plans_controller.rb:424
+#: ../../app/controllers/plans_controller.rb:425
msgid ""
"Unable to change the plan's status since it is needed at least %{percentage} p"
"ercentage responded"
@@ -677,23 +685,23 @@ msgstr ""
"Il est impossible de modifier l’état du plan, car il est nécessaire d’obtenir "
"un taux de réponse d’au moins %{percentage}"
-#: ../../app/controllers/plans_controller.rb:430
+#: ../../app/controllers/plans_controller.rb:431
msgid "Unable to find plan id %{plan_id}"
msgstr "Il est impossible de trouver l’ID du plan %{plan_id}"
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is now a test."
msgstr "Votre projet est maintenant à l’état d’essai."
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is no longer a test."
msgstr "Votre projet n’est plus à l’état d’essai."
-#: ../../app/controllers/plans_controller.rb:449
+#: ../../app/controllers/plans_controller.rb:450
msgid "Unable to change the plan's test status"
msgstr "Il est impossible de modifier l’état d’essai du plan"
-#: ../../app/controllers/plans_controller.rb:462
+#: ../../app/controllers/plans_controller.rb:463
msgid "There is no plan associated with id %{s"
msgstr ""
@@ -783,7 +791,7 @@ msgstr "Le mot de passe et la confirmation doivent être identiques"
msgid "research output not found"
msgstr ""
-#: ../../app/controllers/roles_controller.rb:26
+#: ../../app/controllers/roles_controller.rb:27
msgid ""
"Cannot share plan with %{email} since that email matches\n"
" with the owner of the plan."
@@ -956,27 +964,27 @@ msgstr "Votre compte a bien été associé à %{scheme}."
msgid "Unable to link your account to %{scheme}."
msgstr "Il est impossible d’associer votre compte à %{scheme}."
-#: ../../app/controllers/users_controller.rb:149
+#: ../../app/controllers/users_controller.rb:150
msgid "Successfully %{action} %{username}'s account."
msgstr "La mesure %{action} pour %{username} a été effectuée avec succès."
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "activated"
msgstr "activé"
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "deactivated"
msgstr "désactivé"
-#: ../../app/controllers/users_controller.rb:156
+#: ../../app/controllers/users_controller.rb:157
msgid "Unable to %{action} %{username}"
msgstr "Il est impossible de %{action} %{username}"
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "activate"
msgstr "activer"
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "deactivate"
msgstr "désactiver"
@@ -1270,54 +1278,54 @@ msgstr "Les 9 derniers mois"
msgid "Last 12 months"
msgstr "Les 12 derniers mois"
-#: ../../app/mailers/user_mailer.rb:17
+#: ../../app/mailers/user_mailer.rb:18
#: ../../app/views/devise/mailer/invitation_instructions.html.erb:5
#: ../../app/views/devise/mailer/reset_password_instructions.html.erb:5
#: ../../app/views/user_mailer/_email_signature.html.erb:2
msgid "Query or feedback related to %{tool_name}"
msgstr "Requête ou commentaire associé à %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:25
+#: ../../app/mailers/user_mailer.rb:26
msgid "Welcome to %{tool_name}"
msgstr "Bienvenue à %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:62
+#: ../../app/mailers/user_mailer.rb:63
msgid "A Data Management Plan in %{tool_name} has been shared with you"
msgstr "Un plan de gestion des données dans %{tool_name} a été partagé avec vous"
-#: ../../app/mailers/user_mailer.rb:79
+#: ../../app/mailers/user_mailer.rb:80
msgid "Changed permissions on a Data Management Plan in %{tool_name}"
msgstr ""
"Les autorisations pour un plan de gestion des données dans %{tool_name} sont m"
"odifiées"
-#: ../../app/mailers/user_mailer.rb:94
+#: ../../app/mailers/user_mailer.rb:95
msgid "Permissions removed on a DMP in %{tool_name}"
msgstr "Autorisations relatives à PGD retirées dans %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:112
+#: ../../app/mailers/user_mailer.rb:113
msgid "%{user_name} has requested feedback on a %{tool_name} plan"
msgstr ""
-#: ../../app/mailers/user_mailer.rb:135
+#: ../../app/mailers/user_mailer.rb:136
msgid "%{tool_name}: Expert feedback has been provided for %{plan_title}"
msgstr ""
"%{tool_name}: Les commentaires d’un spécialiste ont été fournis pour %{plan_ti"
"tle}"
-#: ../../app/mailers/user_mailer.rb:153
+#: ../../app/mailers/user_mailer.rb:154
msgid "DMP Visibility Changed: %{plan_title}"
msgstr "Visibilité du PGD modifiée : %{plan_title}"
-#: ../../app/mailers/user_mailer.rb:182
+#: ../../app/mailers/user_mailer.rb:183
msgid "%{tool_name}: A new comment was added to %{plan_title}"
msgstr "%{tool_name}: un nouveau commentaire a été ajouté à %{plan_title}"
-#: ../../app/mailers/user_mailer.rb:198
+#: ../../app/mailers/user_mailer.rb:199
msgid "Administrator privileges granted in %{tool_name}"
msgstr "Privilèges d’administrateur accordés dans %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:216
+#: ../../app/mailers/user_mailer.rb:217
msgid "%{tool_name} API changes"
msgstr "Modifications de l'API pour %{tool_name}"
@@ -1553,15 +1561,15 @@ msgstr ""
msgid "already assigned a value"
msgstr "une valeur a déjà été attribuée"
-#: ../../app/models/org.rb:46
+#: ../../app/models/org.rb:47
msgid "Feedback email message"
msgstr "Courriel de rétroaction"
-#: ../../app/models/org.rb:123
+#: ../../app/models/org.rb:124
msgid "must be one of the following formats: jpeg, jpg, png, gif, bmp"
msgstr "doit être dans l’un des formats suivants: jpeg, jpg, png, gif, bmp"
-#: ../../app/models/org.rb:128
+#: ../../app/models/org.rb:129
msgid "can't be larger than 500KB"
msgstr "ne peut pas dépasser 500 Ko"
@@ -1691,7 +1699,7 @@ msgstr ""
msgid "Conditions in the template refer backwards"
msgstr "Les conditions du modèle sont associées à une référence antérieure"
-#: ../../app/models/user.rb:380
+#: ../../app/models/user.rb:386
msgid "A Data Management Plan in %{application_name} has been shared with you"
msgstr ""
"Un plan de gestion des données dans %{application_name} a été partagé avec vou"
@@ -2122,7 +2130,7 @@ msgstr ""
#: ../../app/views/paginable/templates/_organisational.html.erb:87
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:29
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:36
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
#: ../../app/views/static_pages/about_us.html.erb:22
#: ../../app/views/static_pages/about_us.html.erb:29
#: ../../app/views/static_pages/termsuse.html.erb:46
@@ -4652,7 +4660,7 @@ msgstr ""
msgid "Instructions"
msgstr "Consignes"
-#: ../../app/views/plans/_download_form.html.erb:6
+#: ../../app/views/plans/_download_form.html.erb:5
msgid "Format"
msgstr "Format"
@@ -4660,71 +4668,71 @@ msgstr "Format"
msgid "Download settings"
msgstr "Télécharger les paramètres"
-#: ../../app/views/plans/_download_form.html.erb:19
-msgid "Select phase to download"
-msgstr "Sélectionner la phase à télécharger"
-
-#: ../../app/views/plans/_download_form.html.erb:26
+#: ../../app/views/plans/_download_form.html.erb:21
msgid "Optional plan components"
msgstr "Composants de plan facultatifs"
-#: ../../app/views/plans/_download_form.html.erb:30
+#: ../../app/views/plans/_download_form.html.erb:25
msgid "project details coversheet"
msgstr "page de couverture des détails du projet"
-#: ../../app/views/plans/_download_form.html.erb:36
+#: ../../app/views/plans/_download_form.html.erb:31
msgid "question text and section headings"
msgstr "texte des questions et en-têtes des sections"
-#: ../../app/views/plans/_download_form.html.erb:42
+#: ../../app/views/plans/_download_form.html.erb:37
msgid "unanswered questions"
msgstr "questions sans réponse"
-#: ../../app/views/plans/_download_form.html.erb:49
+#: ../../app/views/plans/_download_form.html.erb:44
msgid "research outputs"
msgstr ""
-#: ../../app/views/plans/_download_form.html.erb:57
+#: ../../app/views/plans/_download_form.html.erb:52
msgid "supplementary section(s) not requested by funding organisation"
msgstr "sections supplémentaires non demandées par l’organisme de financement"
-#: ../../app/views/plans/_download_form.html.erb:65
+#: ../../app/views/plans/_download_form.html.erb:61
+msgid "Select phase to download"
+msgstr "Sélectionner la phase à télécharger"
+
+#: ../../app/views/plans/_download_form.html.erb:70
msgid "PDF formatting"
msgstr "Format PDF"
-#: ../../app/views/plans/_download_form.html.erb:68
+#: ../../app/views/plans/_download_form.html.erb:73
msgid "Font"
msgstr "Police de caractère"
-#: ../../app/views/plans/_download_form.html.erb:71
+#: ../../app/views/plans/_download_form.html.erb:76
msgid "Margin (mm)"
msgstr "Marge (mm)"
-#: ../../app/views/plans/_download_form.html.erb:76
+#: ../../app/views/plans/_download_form.html.erb:81
msgid "Face"
msgstr "Police de caractère"
-#: ../../app/views/plans/_download_form.html.erb:84
+#: ../../app/views/plans/_download_form.html.erb:89
msgid "Size"
msgstr "Taille"
-#: ../../app/views/plans/_download_form.html.erb:92
+#: ../../app/views/plans/_download_form.html.erb:96
msgid "Top"
msgstr "Haut"
-#: ../../app/views/plans/_download_form.html.erb:101
+#: ../../app/views/plans/_download_form.html.erb:105
msgid "Bottom"
msgstr "Bas"
-#: ../../app/views/plans/_download_form.html.erb:110
+#: ../../app/views/plans/_download_form.html.erb:114
msgid "Left"
msgstr "Gauche"
-#: ../../app/views/plans/_download_form.html.erb:119
+#: ../../app/views/plans/_download_form.html.erb:123
msgid "Right"
msgstr "Droite"
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
msgid ""
"Download Plan (new window)%{open_in_new_window_text}"
diff --git a/config/locale/fr_FR/LC_MESSAGES/app.mo b/config/locale/fr_FR/LC_MESSAGES/app.mo
index 281700601f..17404fb0ed 100644
Binary files a/config/locale/fr_FR/LC_MESSAGES/app.mo and b/config/locale/fr_FR/LC_MESSAGES/app.mo differ
diff --git a/config/locale/fr_FR/app.po b/config/locale/fr_FR/app.po
index 739c9150b6..a212b381ce 100644
--- a/config/locale/fr_FR/app.po
+++ b/config/locale/fr_FR/app.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: roadmap_upstream 1.0\n"
"Report-Msgid-Bugs-To: contact@translation.io\n"
-"POT-Creation-Date: 2025-04-10 13:28-0600\n"
-"PO-Revision-Date: 2025-04-10 21:28+0200\n"
+"POT-Creation-Date: 2025-12-23 08:33-0700\n"
+"PO-Revision-Date: 2025-12-23 15:33+0000\n"
"Last-Translator: FULL NAME \n"
"Language-Team: French\n"
"Language: fr_FR\n"
@@ -130,87 +130,95 @@ msgstr "JSON non valide"
msgid "No Plans found"
msgstr "Aucun plan trouvé"
-#: ../../app/controllers/application_controller.rb:36
+#: ../../app/controllers/api/v2/base_api_controller.rb:72
+msgid "There was a problem in the server."
+msgstr ""
+
+#: ../../app/controllers/api/v2/base_api_controller.rb:78
+msgid "The client is not authorized to perform this action."
+msgstr ""
+
+#: ../../app/controllers/application_controller.rb:37
msgid "You are not authorized to perform this action."
msgstr "Vous n'êtes pas autorisé à effectuer cette opération."
-#: ../../app/controllers/application_controller.rb:40
+#: ../../app/controllers/application_controller.rb:41
msgid "You need to sign in or sign up before continuing."
msgstr "Vous devez vous connecter ou vous enregistrer afin de continuer."
-#: ../../app/controllers/application_controller.rb:108
+#: ../../app/controllers/application_controller.rb:115
msgid "Unable to %{action} the %{object}. %{errors}"
msgstr "Impossible de %{action} le %{object}. %{errors}"
-#: ../../app/controllers/application_controller.rb:114
+#: ../../app/controllers/application_controller.rb:121
msgid "Successfully %{action} the %{object}."
msgstr "%{object} %{action} avec succès."
-#: ../../app/controllers/application_controller.rb:127
+#: ../../app/controllers/application_controller.rb:134
msgid "API client"
msgstr "Client API"
-#: ../../app/controllers/application_controller.rb:128
+#: ../../app/controllers/application_controller.rb:135
msgid "plan"
msgstr "plan"
-#: ../../app/controllers/application_controller.rb:129
+#: ../../app/controllers/application_controller.rb:136
msgid "guidance group"
msgstr "Groupe de recommandations"
-#: ../../app/controllers/application_controller.rb:130
+#: ../../app/controllers/application_controller.rb:137
msgid "comment"
msgstr "Commentaire"
-#: ../../app/controllers/application_controller.rb:131
+#: ../../app/controllers/application_controller.rb:138
msgid "organisation"
msgstr "organisme"
-#: ../../app/controllers/application_controller.rb:132
+#: ../../app/controllers/application_controller.rb:139
msgid "permission"
msgstr "autorisation"
-#: ../../app/controllers/application_controller.rb:133
+#: ../../app/controllers/application_controller.rb:140
msgid "preferences"
msgstr "préférences"
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "profile"
msgstr "profil"
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "user"
msgstr "utilisateur"
-#: ../../app/controllers/application_controller.rb:135
+#: ../../app/controllers/application_controller.rb:142
msgid "question option"
msgstr "option de question"
-#: ../../app/controllers/application_controller.rb:181
+#: ../../app/controllers/application_controller.rb:188
msgid "Record Not Found"
msgstr "Enregistrement non trouvé"
-#: ../../app/controllers/concerns/paginable.rb:45
+#: ../../app/controllers/concerns/paginable.rb:46
msgid "scope should be an ActiveRecord::Relation object"
msgstr "scope doit être un objet de type ActiveRecord::Relation"
-#: ../../app/controllers/concerns/paginable.rb:47
+#: ../../app/controllers/concerns/paginable.rb:48
msgid "path_params should be a Hash object"
msgstr "path_params doit être un objet de type Hash"
-#: ../../app/controllers/concerns/paginable.rb:48
+#: ../../app/controllers/concerns/paginable.rb:49
msgid "query_params should be a Hash object"
msgstr "query_params doit être un objet de type Hash"
-#: ../../app/controllers/concerns/paginable.rb:49
+#: ../../app/controllers/concerns/paginable.rb:50
msgid "locals should be a Hash object"
msgstr "locals doit être un objet de type Hash"
-#: ../../app/controllers/concerns/paginable.rb:70
+#: ../../app/controllers/concerns/paginable.rb:71
msgid "Restricted access to View All the records"
msgstr "Accès restreint à Voir tous les enregistrements"
-#: ../../app/controllers/concerns/paginable.rb:183
+#: ../../app/controllers/concerns/paginable.rb:184
msgid "Sort by %{sort_field}"
msgstr "Trier par %{sort_field}"
@@ -251,77 +259,77 @@ msgstr "Mail de contact envoyé avec succès."
msgid "Unable to submit your request"
msgstr "Impossible de soumettre votre demande"
-#: ../../app/controllers/contributors_controller.rb:40
-#: ../../app/controllers/contributors_controller.rb:56
+#: ../../app/controllers/contributors_controller.rb:41
+#: ../../app/controllers/contributors_controller.rb:57
#: ../../app/controllers/research_outputs_controller.rb:42
msgid "add"
msgstr "ajouter"
-#: ../../app/controllers/contributors_controller.rb:54
+#: ../../app/controllers/contributors_controller.rb:55
#: ../../app/controllers/research_outputs_controller.rb:40
msgid "added"
msgstr "ajouté"
-#: ../../app/controllers/contributors_controller.rb:72
+#: ../../app/controllers/contributors_controller.rb:73
#: ../../app/controllers/guidance_groups_controller.rb:55
#: ../../app/controllers/guidances_controller.rb:75
-#: ../../app/controllers/notes_controller.rb:88
+#: ../../app/controllers/notes_controller.rb:89
#: ../../app/controllers/org_admin/departments_controller.rb:50
#: ../../app/controllers/org_admin/sections_controller.rb:103
#: ../../app/controllers/org_admin/templates_controller.rb:210
#: ../../app/controllers/orgs_controller.rb:92
-#: ../../app/controllers/plans_controller.rb:280
-#: ../../app/controllers/plans_controller.rb:283
+#: ../../app/controllers/plans_controller.rb:281
+#: ../../app/controllers/plans_controller.rb:284
#: ../../app/controllers/registrations_controller.rb:249
#: ../../app/controllers/registrations_controller.rb:253
#: ../../app/controllers/registrations_controller.rb:280
#: ../../app/controllers/registrations_controller.rb:284
#: ../../app/controllers/research_outputs_controller.rb:60
-#: ../../app/controllers/users_controller.rb:103
-#: ../../app/controllers/users_controller.rb:131
+#: ../../app/controllers/users_controller.rb:104
+#: ../../app/controllers/users_controller.rb:132
msgid "saved"
msgstr "enregistré"
-#: ../../app/controllers/contributors_controller.rb:74
+#: ../../app/controllers/contributors_controller.rb:75
#: ../../app/controllers/guidance_groups_controller.rb:57
#: ../../app/controllers/guidances_controller.rb:77
-#: ../../app/controllers/notes_controller.rb:106
+#: ../../app/controllers/notes_controller.rb:107
#: ../../app/controllers/org_admin/departments_controller.rb:52
#: ../../app/controllers/org_admin/sections_controller.rb:105
#: ../../app/controllers/org_admin/templates_controller.rb:215
#: ../../app/controllers/orgs_controller.rb:94
-#: ../../app/controllers/plans_controller.rb:289
-#: ../../app/controllers/plans_controller.rb:292
-#: ../../app/controllers/plans_controller.rb:296
-#: ../../app/controllers/plans_controller.rb:299
+#: ../../app/controllers/plans_controller.rb:290
+#: ../../app/controllers/plans_controller.rb:293
+#: ../../app/controllers/plans_controller.rb:297
+#: ../../app/controllers/plans_controller.rb:300
#: ../../app/controllers/registrations_controller.rb:256
#: ../../app/controllers/registrations_controller.rb:287
#: ../../app/controllers/research_outputs_controller.rb:63
msgid "save"
msgstr "enregistrer"
-#: ../../app/controllers/contributors_controller.rb:83
-#: ../../app/controllers/notes_controller.rb:130
+#: ../../app/controllers/contributors_controller.rb:84
+#: ../../app/controllers/notes_controller.rb:131
#: ../../app/controllers/org_admin/templates_controller.rb:243
#: ../../app/controllers/research_outputs_controller.rb:74
#: ../../app/controllers/super_admin/orgs_controller.rb:94
msgid "removed"
msgstr "supprimé(e)"
-#: ../../app/controllers/contributors_controller.rb:86
-#: ../../app/controllers/notes_controller.rb:148
+#: ../../app/controllers/contributors_controller.rb:87
+#: ../../app/controllers/notes_controller.rb:149
#: ../../app/controllers/org_admin/templates_controller.rb:245
#: ../../app/controllers/research_outputs_controller.rb:77
#: ../../app/controllers/super_admin/orgs_controller.rb:97
msgid "remove"
msgstr "supprimer"
-#: ../../app/controllers/contributors_controller.rb:160
+#: ../../app/controllers/contributors_controller.rb:161
#: ../../app/controllers/research_outputs_controller.rb:208
msgid "plan not found"
msgstr "Plan non trouvé"
-#: ../../app/controllers/contributors_controller.rb:168
+#: ../../app/controllers/contributors_controller.rb:169
msgid "contributor not found"
msgstr "contributeur non trouvé"
@@ -335,7 +343,7 @@ msgstr "Une erreur s'est produite lors de la demande de commentaires sur ce plan
#: ../../app/controllers/guidance_groups_controller.rb:31
#: ../../app/controllers/guidances_controller.rb:53
-#: ../../app/controllers/notes_controller.rb:47
+#: ../../app/controllers/notes_controller.rb:48
#: ../../app/controllers/org_admin/departments_controller.rb:26
#: ../../app/controllers/org_admin/phases_controller.rb:121
#: ../../app/controllers/org_admin/questions_controller.rb:94
@@ -351,7 +359,7 @@ msgstr "créé"
#: ../../app/controllers/guidance_groups_controller.rb:34
#: ../../app/controllers/guidances_controller.rb:55
-#: ../../app/controllers/notes_controller.rb:66
+#: ../../app/controllers/notes_controller.rb:67
#: ../../app/controllers/org_admin/departments_controller.rb:30
#: ../../app/controllers/org_admin/phases_controller.rb:123
#: ../../app/controllers/org_admin/questions_controller.rb:96
@@ -394,7 +402,7 @@ msgstr "dépublier"
#: ../../app/controllers/org_admin/question_options_controller.rb:24
#: ../../app/controllers/org_admin/questions_controller.rb:197
#: ../../app/controllers/org_admin/sections_controller.rb:128
-#: ../../app/controllers/plans_controller.rb:342
+#: ../../app/controllers/plans_controller.rb:343
#: ../../app/controllers/super_admin/api_clients_controller.rb:81
#: ../../app/controllers/super_admin/notifications_controller.rb:85
#: ../../app/controllers/super_admin/themes_controller.rb:51
@@ -408,7 +416,7 @@ msgstr "supprimé"
#: ../../app/controllers/org_admin/question_options_controller.rb:26
#: ../../app/controllers/org_admin/questions_controller.rb:199
#: ../../app/controllers/org_admin/sections_controller.rb:130
-#: ../../app/controllers/plans_controller.rb:347
+#: ../../app/controllers/plans_controller.rb:348
#: ../../app/controllers/super_admin/api_clients_controller.rb:84
#: ../../app/controllers/super_admin/notifications_controller.rb:88
#: ../../app/controllers/super_admin/themes_controller.rb:54
@@ -453,19 +461,19 @@ msgstr "Impossible de créer une nouvelle version de ce modèle.
"
#: ../../app/controllers/org_admin/phases_controller.rb:147
#: ../../app/controllers/org_admin/questions_controller.rb:166
#: ../../app/controllers/org_admin/users_controller.rb:30
-#: ../../app/controllers/plans_controller.rb:416
+#: ../../app/controllers/plans_controller.rb:417
#: ../../app/controllers/super_admin/api_clients_controller.rb:68
#: ../../app/controllers/super_admin/notifications_controller.rb:52
#: ../../app/controllers/super_admin/themes_controller.rb:39
#: ../../app/controllers/super_admin/users_controller.rb:54
-#: ../../app/controllers/users_controller.rb:108
+#: ../../app/controllers/users_controller.rb:109
msgid "updated"
msgstr "mis à jour"
#: ../../app/controllers/org_admin/phases_controller.rb:149
#: ../../app/controllers/org_admin/questions_controller.rb:169
#: ../../app/controllers/org_admin/users_controller.rb:32
-#: ../../app/controllers/plans_controller.rb:419
+#: ../../app/controllers/plans_controller.rb:420
#: ../../app/controllers/super_admin/api_clients_controller.rb:70
#: ../../app/controllers/super_admin/notifications_controller.rb:55
#: ../../app/controllers/super_admin/themes_controller.rb:41
@@ -559,7 +567,7 @@ msgid "Unable to delete this version of the template."
msgstr "Impossible de supprimer cette version du modèle."
#: ../../app/controllers/org_admin/template_copies_controller.rb:20
-#: ../../app/controllers/plans_controller.rb:395
+#: ../../app/controllers/plans_controller.rb:396
msgid "copy"
msgstr "copier"
@@ -568,11 +576,11 @@ msgstr "copier"
msgid "That template is no longer customizable."
msgstr "Ce template n'est plus personnalisable."
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:21
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:22
msgid "Unable to customize that template."
msgstr "Impossible de personnaliser ce modèle."
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:24
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:25
msgid "That template is not customizable."
msgstr "Ce modèle n'est pas personnalisable."
@@ -662,11 +670,11 @@ msgstr "Ce plan est basé sur le"
msgid "template with customisations by the"
msgstr "modèle personnalisé par"
-#: ../../app/controllers/plans_controller.rb:393
+#: ../../app/controllers/plans_controller.rb:394
msgid "copied"
msgstr "copié"
-#: ../../app/controllers/plans_controller.rb:424
+#: ../../app/controllers/plans_controller.rb:425
msgid ""
"Unable to change the plan's status since it is needed at least %{percentage} p"
"ercentage responded"
@@ -674,23 +682,23 @@ msgstr ""
"Impossible de changer le statut du plan, au moins %{percentage} % de questions"
" répondues sont nécessaires"
-#: ../../app/controllers/plans_controller.rb:430
+#: ../../app/controllers/plans_controller.rb:431
msgid "Unable to find plan id %{plan_id}"
msgstr "Impossible de trouver le plan avec l'identifiant %{plan_id}"
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is now a test."
msgstr "Votre projet est maintenant un test."
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is no longer a test."
msgstr "Votre projet n'est plus un test."
-#: ../../app/controllers/plans_controller.rb:449
+#: ../../app/controllers/plans_controller.rb:450
msgid "Unable to change the plan's test status"
msgstr "Impossible de changer le statut du plan"
-#: ../../app/controllers/plans_controller.rb:462
+#: ../../app/controllers/plans_controller.rb:463
msgid "There is no plan associated with id %{s"
msgstr "Il n'y a pas de forfait associé à l'identifiant %{ s"
@@ -788,7 +796,7 @@ msgstr "Le mot de passe et sa confirmation doivent correspondre"
msgid "research output not found"
msgstr "produit de recherche introuvable"
-#: ../../app/controllers/roles_controller.rb:26
+#: ../../app/controllers/roles_controller.rb:27
msgid ""
"Cannot share plan with %{email} since that email matches\n"
" with the owner of the plan."
@@ -967,27 +975,27 @@ msgstr "Votre compte a été lié à %{scheme} avec succès."
msgid "Unable to link your account to %{scheme}."
msgstr "Impossible de lier votre compte avec %{scheme}."
-#: ../../app/controllers/users_controller.rb:149
+#: ../../app/controllers/users_controller.rb:150
msgid "Successfully %{action} %{username}'s account."
msgstr "Compte de %{username} %{action} avec succès."
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "activated"
msgstr "activé"
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "deactivated"
msgstr "désactivé"
-#: ../../app/controllers/users_controller.rb:156
+#: ../../app/controllers/users_controller.rb:157
msgid "Unable to %{action} %{username}"
msgstr "Impossible de %{action} %{username}"
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "activate"
msgstr "activer"
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "deactivate"
msgstr "désactiver"
@@ -1280,50 +1288,50 @@ msgstr "9 derniers mois"
msgid "Last 12 months"
msgstr "12 derniers mois"
-#: ../../app/mailers/user_mailer.rb:17
+#: ../../app/mailers/user_mailer.rb:18
#: ../../app/views/devise/mailer/invitation_instructions.html.erb:5
#: ../../app/views/devise/mailer/reset_password_instructions.html.erb:5
#: ../../app/views/user_mailer/_email_signature.html.erb:2
msgid "Query or feedback related to %{tool_name}"
msgstr "Requête ou suggestion liée à %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:25
+#: ../../app/mailers/user_mailer.rb:26
msgid "Welcome to %{tool_name}"
msgstr "Bienvenue sur %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:62
+#: ../../app/mailers/user_mailer.rb:63
msgid "A Data Management Plan in %{tool_name} has been shared with you"
msgstr "Un plan de gestion de données a été partagé avec vous sur %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:79
+#: ../../app/mailers/user_mailer.rb:80
msgid "Changed permissions on a Data Management Plan in %{tool_name}"
msgstr "Modification des autorisations sur un plan de %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:94
+#: ../../app/mailers/user_mailer.rb:95
msgid "Permissions removed on a DMP in %{tool_name}"
msgstr "Autorisations retirées d'un plan de %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:112
+#: ../../app/mailers/user_mailer.rb:113
msgid "%{user_name} has requested feedback on a %{tool_name} plan"
msgstr "%{user_name} a demandé une assistance conseil pour un plan %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:135
+#: ../../app/mailers/user_mailer.rb:136
msgid "%{tool_name}: Expert feedback has been provided for %{plan_title}"
msgstr "%{tool_name} : Une assistance conseil a été fournie pour %{plan_title}"
-#: ../../app/mailers/user_mailer.rb:153
+#: ../../app/mailers/user_mailer.rb:154
msgid "DMP Visibility Changed: %{plan_title}"
msgstr "Changement de visibilité d'un plan : %{plan_title}"
-#: ../../app/mailers/user_mailer.rb:182
+#: ../../app/mailers/user_mailer.rb:183
msgid "%{tool_name}: A new comment was added to %{plan_title}"
msgstr "%{tool_name}: Un nouveau commentaire a été ajouté à %{plan_title}"
-#: ../../app/mailers/user_mailer.rb:198
+#: ../../app/mailers/user_mailer.rb:199
msgid "Administrator privileges granted in %{tool_name}"
msgstr "Droits administrateur attribués dans %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:216
+#: ../../app/mailers/user_mailer.rb:217
msgid "%{tool_name} API changes"
msgstr "Modifications de l'API %{tool_name}"
@@ -1564,15 +1572,15 @@ msgstr ""
msgid "already assigned a value"
msgstr "a déjà une valeur attribuée"
-#: ../../app/models/org.rb:46
+#: ../../app/models/org.rb:47
msgid "Feedback email message"
msgstr "Message du mail de l'assistance conseil"
-#: ../../app/models/org.rb:123
+#: ../../app/models/org.rb:124
msgid "must be one of the following formats: jpeg, jpg, png, gif, bmp"
msgstr "doit être dans l'un des formats suivants : jpeg, jpg, png, gif, bmp"
-#: ../../app/models/org.rb:128
+#: ../../app/models/org.rb:129
msgid "can't be larger than 500KB"
msgstr "ne peut peser plus de 500ko"
@@ -1700,7 +1708,7 @@ msgstr ""
"Les conditions du modèle s'appliquent à une question positionnée avant celle-c"
"i"
-#: ../../app/models/user.rb:380
+#: ../../app/models/user.rb:386
msgid "A Data Management Plan in %{application_name} has been shared with you"
msgstr "Un plan de gestion de données a été partagé avec vous sur %{application_name}"
@@ -2128,7 +2136,7 @@ msgstr ""
#: ../../app/views/paginable/templates/_organisational.html.erb:87
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:29
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:36
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
#: ../../app/views/static_pages/about_us.html.erb:22
#: ../../app/views/static_pages/about_us.html.erb:29
#: ../../app/views/static_pages/termsuse.html.erb:46
@@ -4654,7 +4662,7 @@ msgstr "Commentaires & Recommandations"
msgid "Instructions"
msgstr "Instructions"
-#: ../../app/views/plans/_download_form.html.erb:6
+#: ../../app/views/plans/_download_form.html.erb:5
msgid "Format"
msgstr "Format"
@@ -4662,71 +4670,71 @@ msgstr "Format"
msgid "Download settings"
msgstr "Paramètres de téléchargement"
-#: ../../app/views/plans/_download_form.html.erb:19
-msgid "Select phase to download"
-msgstr "Sélectionner la phase à télécharger"
-
-#: ../../app/views/plans/_download_form.html.erb:26
+#: ../../app/views/plans/_download_form.html.erb:21
msgid "Optional plan components"
msgstr "Eléments optionnels du plan"
-#: ../../app/views/plans/_download_form.html.erb:30
+#: ../../app/views/plans/_download_form.html.erb:25
msgid "project details coversheet"
msgstr "page de renseignements sur le projet"
-#: ../../app/views/plans/_download_form.html.erb:36
+#: ../../app/views/plans/_download_form.html.erb:31
msgid "question text and section headings"
msgstr "texte de la question et entête de la section"
-#: ../../app/views/plans/_download_form.html.erb:42
+#: ../../app/views/plans/_download_form.html.erb:37
msgid "unanswered questions"
msgstr "questions non répondues"
-#: ../../app/views/plans/_download_form.html.erb:49
+#: ../../app/views/plans/_download_form.html.erb:44
msgid "research outputs"
msgstr "produits de recherche"
-#: ../../app/views/plans/_download_form.html.erb:57
+#: ../../app/views/plans/_download_form.html.erb:52
msgid "supplementary section(s) not requested by funding organisation"
msgstr "section(s) supplémentaire(s) non requise(s) par l'organisme financeur"
-#: ../../app/views/plans/_download_form.html.erb:65
+#: ../../app/views/plans/_download_form.html.erb:61
+msgid "Select phase to download"
+msgstr "Sélectionner la phase à télécharger"
+
+#: ../../app/views/plans/_download_form.html.erb:70
msgid "PDF formatting"
msgstr "Mise en forme du PDF"
-#: ../../app/views/plans/_download_form.html.erb:68
+#: ../../app/views/plans/_download_form.html.erb:73
msgid "Font"
msgstr "Police de caractères"
-#: ../../app/views/plans/_download_form.html.erb:71
+#: ../../app/views/plans/_download_form.html.erb:76
msgid "Margin (mm)"
msgstr "Marge (mm)"
-#: ../../app/views/plans/_download_form.html.erb:76
+#: ../../app/views/plans/_download_form.html.erb:81
msgid "Face"
msgstr "Police"
-#: ../../app/views/plans/_download_form.html.erb:84
+#: ../../app/views/plans/_download_form.html.erb:89
msgid "Size"
msgstr "Taille"
-#: ../../app/views/plans/_download_form.html.erb:92
+#: ../../app/views/plans/_download_form.html.erb:96
msgid "Top"
msgstr "Haut"
-#: ../../app/views/plans/_download_form.html.erb:101
+#: ../../app/views/plans/_download_form.html.erb:105
msgid "Bottom"
msgstr "Bas"
-#: ../../app/views/plans/_download_form.html.erb:110
+#: ../../app/views/plans/_download_form.html.erb:114
msgid "Left"
msgstr "Gauche"
-#: ../../app/views/plans/_download_form.html.erb:119
+#: ../../app/views/plans/_download_form.html.erb:123
msgid "Right"
msgstr "Droite"
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
msgid ""
"Download Plan (new window)%{open_in_new_window_text}"
diff --git a/config/locale/pt_BR/LC_MESSAGES/app.mo b/config/locale/pt_BR/LC_MESSAGES/app.mo
index 48f01f060c..6695cbe96a 100644
Binary files a/config/locale/pt_BR/LC_MESSAGES/app.mo and b/config/locale/pt_BR/LC_MESSAGES/app.mo differ
diff --git a/config/locale/pt_BR/app.po b/config/locale/pt_BR/app.po
index 44e4aeb102..a401ad5aad 100644
--- a/config/locale/pt_BR/app.po
+++ b/config/locale/pt_BR/app.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: roadmap_upstream 1.0\n"
"Report-Msgid-Bugs-To: contact@translation.io\n"
-"POT-Creation-Date: 2025-04-10 13:28-0600\n"
-"PO-Revision-Date: 2025-04-10 21:28+0200\n"
+"POT-Creation-Date: 2025-12-23 08:33-0700\n"
+"PO-Revision-Date: 2025-12-23 15:33+0000\n"
"Last-Translator: FULL NAME \n"
"Language-Team: Portuguese\n"
"Language: pt_BR\n"
@@ -127,87 +127,95 @@ msgstr "JSON inválido"
msgid "No Plans found"
msgstr "Nenhum plano encontrado"
-#: ../../app/controllers/application_controller.rb:36
+#: ../../app/controllers/api/v2/base_api_controller.rb:72
+msgid "There was a problem in the server."
+msgstr ""
+
+#: ../../app/controllers/api/v2/base_api_controller.rb:78
+msgid "The client is not authorized to perform this action."
+msgstr ""
+
+#: ../../app/controllers/application_controller.rb:37
msgid "You are not authorized to perform this action."
msgstr "Você não tem permissão para realizar essa ação."
-#: ../../app/controllers/application_controller.rb:40
+#: ../../app/controllers/application_controller.rb:41
msgid "You need to sign in or sign up before continuing."
msgstr "Você precisa entrar ou registrar-se antes de continuar."
-#: ../../app/controllers/application_controller.rb:108
+#: ../../app/controllers/application_controller.rb:115
msgid "Unable to %{action} the %{object}. %{errors}"
msgstr "Não é possível %{action} o %{object}. %{errors}"
-#: ../../app/controllers/application_controller.rb:114
+#: ../../app/controllers/application_controller.rb:121
msgid "Successfully %{action} the %{object}."
msgstr "Com sucesso %{action} o %{object}."
-#: ../../app/controllers/application_controller.rb:127
+#: ../../app/controllers/application_controller.rb:134
msgid "API client"
msgstr "Cliente da API"
-#: ../../app/controllers/application_controller.rb:128
+#: ../../app/controllers/application_controller.rb:135
msgid "plan"
msgstr "plano"
-#: ../../app/controllers/application_controller.rb:129
+#: ../../app/controllers/application_controller.rb:136
msgid "guidance group"
msgstr "grupo de instruções"
-#: ../../app/controllers/application_controller.rb:130
+#: ../../app/controllers/application_controller.rb:137
msgid "comment"
msgstr "commentário"
-#: ../../app/controllers/application_controller.rb:131
+#: ../../app/controllers/application_controller.rb:138
msgid "organisation"
msgstr "organização"
-#: ../../app/controllers/application_controller.rb:132
+#: ../../app/controllers/application_controller.rb:139
msgid "permission"
msgstr "permissão"
-#: ../../app/controllers/application_controller.rb:133
+#: ../../app/controllers/application_controller.rb:140
msgid "preferences"
msgstr "preferências"
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "profile"
msgstr "perfil"
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "user"
msgstr "usuário"
-#: ../../app/controllers/application_controller.rb:135
+#: ../../app/controllers/application_controller.rb:142
msgid "question option"
msgstr "opção de pergunta"
-#: ../../app/controllers/application_controller.rb:181
+#: ../../app/controllers/application_controller.rb:188
msgid "Record Not Found"
msgstr "Registro não encontrado"
-#: ../../app/controllers/concerns/paginable.rb:45
+#: ../../app/controllers/concerns/paginable.rb:46
msgid "scope should be an ActiveRecord::Relation object"
msgstr "escopo deve ser um objeto ActiveRecord::Relation"
-#: ../../app/controllers/concerns/paginable.rb:47
+#: ../../app/controllers/concerns/paginable.rb:48
msgid "path_params should be a Hash object"
msgstr "path_params deve ser um objeto hash"
-#: ../../app/controllers/concerns/paginable.rb:48
+#: ../../app/controllers/concerns/paginable.rb:49
msgid "query_params should be a Hash object"
msgstr "query_params deve ser um objeto hash"
-#: ../../app/controllers/concerns/paginable.rb:49
+#: ../../app/controllers/concerns/paginable.rb:50
msgid "locals should be a Hash object"
msgstr "locals deve ser um objeto Hash"
-#: ../../app/controllers/concerns/paginable.rb:70
+#: ../../app/controllers/concerns/paginable.rb:71
msgid "Restricted access to View All the records"
msgstr "Acesso restrito para visualizar todos os registros"
-#: ../../app/controllers/concerns/paginable.rb:183
+#: ../../app/controllers/concerns/paginable.rb:184
msgid "Sort by %{sort_field}"
msgstr "Classificar por %{sort_field}"
@@ -248,77 +256,77 @@ msgstr "Email de contato foi enviado com sucesso."
msgid "Unable to submit your request"
msgstr "Não é possível enviar sua solicitação"
-#: ../../app/controllers/contributors_controller.rb:40
-#: ../../app/controllers/contributors_controller.rb:56
+#: ../../app/controllers/contributors_controller.rb:41
+#: ../../app/controllers/contributors_controller.rb:57
#: ../../app/controllers/research_outputs_controller.rb:42
msgid "add"
msgstr "Adicionar"
-#: ../../app/controllers/contributors_controller.rb:54
+#: ../../app/controllers/contributors_controller.rb:55
#: ../../app/controllers/research_outputs_controller.rb:40
msgid "added"
msgstr "adicionado"
-#: ../../app/controllers/contributors_controller.rb:72
+#: ../../app/controllers/contributors_controller.rb:73
#: ../../app/controllers/guidance_groups_controller.rb:55
#: ../../app/controllers/guidances_controller.rb:75
-#: ../../app/controllers/notes_controller.rb:88
+#: ../../app/controllers/notes_controller.rb:89
#: ../../app/controllers/org_admin/departments_controller.rb:50
#: ../../app/controllers/org_admin/sections_controller.rb:103
#: ../../app/controllers/org_admin/templates_controller.rb:210
#: ../../app/controllers/orgs_controller.rb:92
-#: ../../app/controllers/plans_controller.rb:280
-#: ../../app/controllers/plans_controller.rb:283
+#: ../../app/controllers/plans_controller.rb:281
+#: ../../app/controllers/plans_controller.rb:284
#: ../../app/controllers/registrations_controller.rb:249
#: ../../app/controllers/registrations_controller.rb:253
#: ../../app/controllers/registrations_controller.rb:280
#: ../../app/controllers/registrations_controller.rb:284
#: ../../app/controllers/research_outputs_controller.rb:60
-#: ../../app/controllers/users_controller.rb:103
-#: ../../app/controllers/users_controller.rb:131
+#: ../../app/controllers/users_controller.rb:104
+#: ../../app/controllers/users_controller.rb:132
msgid "saved"
msgstr "salvo"
-#: ../../app/controllers/contributors_controller.rb:74
+#: ../../app/controllers/contributors_controller.rb:75
#: ../../app/controllers/guidance_groups_controller.rb:57
#: ../../app/controllers/guidances_controller.rb:77
-#: ../../app/controllers/notes_controller.rb:106
+#: ../../app/controllers/notes_controller.rb:107
#: ../../app/controllers/org_admin/departments_controller.rb:52
#: ../../app/controllers/org_admin/sections_controller.rb:105
#: ../../app/controllers/org_admin/templates_controller.rb:215
#: ../../app/controllers/orgs_controller.rb:94
-#: ../../app/controllers/plans_controller.rb:289
-#: ../../app/controllers/plans_controller.rb:292
-#: ../../app/controllers/plans_controller.rb:296
-#: ../../app/controllers/plans_controller.rb:299
+#: ../../app/controllers/plans_controller.rb:290
+#: ../../app/controllers/plans_controller.rb:293
+#: ../../app/controllers/plans_controller.rb:297
+#: ../../app/controllers/plans_controller.rb:300
#: ../../app/controllers/registrations_controller.rb:256
#: ../../app/controllers/registrations_controller.rb:287
#: ../../app/controllers/research_outputs_controller.rb:63
msgid "save"
msgstr "Salvar"
-#: ../../app/controllers/contributors_controller.rb:83
-#: ../../app/controllers/notes_controller.rb:130
+#: ../../app/controllers/contributors_controller.rb:84
+#: ../../app/controllers/notes_controller.rb:131
#: ../../app/controllers/org_admin/templates_controller.rb:243
#: ../../app/controllers/research_outputs_controller.rb:74
#: ../../app/controllers/super_admin/orgs_controller.rb:94
msgid "removed"
msgstr "removido"
-#: ../../app/controllers/contributors_controller.rb:86
-#: ../../app/controllers/notes_controller.rb:148
+#: ../../app/controllers/contributors_controller.rb:87
+#: ../../app/controllers/notes_controller.rb:149
#: ../../app/controllers/org_admin/templates_controller.rb:245
#: ../../app/controllers/research_outputs_controller.rb:77
#: ../../app/controllers/super_admin/orgs_controller.rb:97
msgid "remove"
msgstr "Remover"
-#: ../../app/controllers/contributors_controller.rb:160
+#: ../../app/controllers/contributors_controller.rb:161
#: ../../app/controllers/research_outputs_controller.rb:208
msgid "plan not found"
msgstr "plano não encontrado"
-#: ../../app/controllers/contributors_controller.rb:168
+#: ../../app/controllers/contributors_controller.rb:169
msgid "contributor not found"
msgstr "colaborador não encontrado"
@@ -332,7 +340,7 @@ msgstr "Ocorreu um erro ao solicitar feedback para este plano."
#: ../../app/controllers/guidance_groups_controller.rb:31
#: ../../app/controllers/guidances_controller.rb:53
-#: ../../app/controllers/notes_controller.rb:47
+#: ../../app/controllers/notes_controller.rb:48
#: ../../app/controllers/org_admin/departments_controller.rb:26
#: ../../app/controllers/org_admin/phases_controller.rb:121
#: ../../app/controllers/org_admin/questions_controller.rb:94
@@ -348,7 +356,7 @@ msgstr "criado"
#: ../../app/controllers/guidance_groups_controller.rb:34
#: ../../app/controllers/guidances_controller.rb:55
-#: ../../app/controllers/notes_controller.rb:66
+#: ../../app/controllers/notes_controller.rb:67
#: ../../app/controllers/org_admin/departments_controller.rb:30
#: ../../app/controllers/org_admin/phases_controller.rb:123
#: ../../app/controllers/org_admin/questions_controller.rb:96
@@ -391,7 +399,7 @@ msgstr "cancelar publicação"
#: ../../app/controllers/org_admin/question_options_controller.rb:24
#: ../../app/controllers/org_admin/questions_controller.rb:197
#: ../../app/controllers/org_admin/sections_controller.rb:128
-#: ../../app/controllers/plans_controller.rb:342
+#: ../../app/controllers/plans_controller.rb:343
#: ../../app/controllers/super_admin/api_clients_controller.rb:81
#: ../../app/controllers/super_admin/notifications_controller.rb:85
#: ../../app/controllers/super_admin/themes_controller.rb:51
@@ -405,7 +413,7 @@ msgstr "apagado"
#: ../../app/controllers/org_admin/question_options_controller.rb:26
#: ../../app/controllers/org_admin/questions_controller.rb:199
#: ../../app/controllers/org_admin/sections_controller.rb:130
-#: ../../app/controllers/plans_controller.rb:347
+#: ../../app/controllers/plans_controller.rb:348
#: ../../app/controllers/super_admin/api_clients_controller.rb:84
#: ../../app/controllers/super_admin/notifications_controller.rb:88
#: ../../app/controllers/super_admin/themes_controller.rb:54
@@ -450,19 +458,19 @@ msgstr "Não foi possível criar uma nova versão deste modelo.
"
#: ../../app/controllers/org_admin/phases_controller.rb:147
#: ../../app/controllers/org_admin/questions_controller.rb:166
#: ../../app/controllers/org_admin/users_controller.rb:30
-#: ../../app/controllers/plans_controller.rb:416
+#: ../../app/controllers/plans_controller.rb:417
#: ../../app/controllers/super_admin/api_clients_controller.rb:68
#: ../../app/controllers/super_admin/notifications_controller.rb:52
#: ../../app/controllers/super_admin/themes_controller.rb:39
#: ../../app/controllers/super_admin/users_controller.rb:54
-#: ../../app/controllers/users_controller.rb:108
+#: ../../app/controllers/users_controller.rb:109
msgid "updated"
msgstr "Atualizado"
#: ../../app/controllers/org_admin/phases_controller.rb:149
#: ../../app/controllers/org_admin/questions_controller.rb:169
#: ../../app/controllers/org_admin/users_controller.rb:32
-#: ../../app/controllers/plans_controller.rb:419
+#: ../../app/controllers/plans_controller.rb:420
#: ../../app/controllers/super_admin/api_clients_controller.rb:70
#: ../../app/controllers/super_admin/notifications_controller.rb:55
#: ../../app/controllers/super_admin/themes_controller.rb:41
@@ -552,7 +560,7 @@ msgid "Unable to delete this version of the template."
msgstr "Não foi possível excluir esta versão do modelo."
#: ../../app/controllers/org_admin/template_copies_controller.rb:20
-#: ../../app/controllers/plans_controller.rb:395
+#: ../../app/controllers/plans_controller.rb:396
msgid "copy"
msgstr "cópia"
@@ -561,11 +569,11 @@ msgstr "cópia"
msgid "That template is no longer customizable."
msgstr "Esse modelo não é mais customizáveis."
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:21
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:22
msgid "Unable to customize that template."
msgstr "Não customização esse modelo."
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:24
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:25
msgid "That template is not customizable."
msgstr "Esse modelo não é customizáveis."
@@ -655,11 +663,11 @@ msgstr "Este plano é baseado no"
msgid "template with customisations by the"
msgstr "modelo com personalizações pelo"
-#: ../../app/controllers/plans_controller.rb:393
+#: ../../app/controllers/plans_controller.rb:394
msgid "copied"
msgstr "copieado"
-#: ../../app/controllers/plans_controller.rb:424
+#: ../../app/controllers/plans_controller.rb:425
msgid ""
"Unable to change the plan's status since it is needed at least %{percentage} p"
"ercentage responded"
@@ -667,23 +675,23 @@ msgstr ""
"Não conseguimos mudar o status do plano. É preciso pelo menos %{percentage} de"
" respostas."
-#: ../../app/controllers/plans_controller.rb:430
+#: ../../app/controllers/plans_controller.rb:431
msgid "Unable to find plan id %{plan_id}"
msgstr "Não conseguimos encontrar o plano com id %{plan_id}"
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is now a test."
msgstr "Seu projeto agora é um teste."
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is no longer a test."
msgstr "Seu projeto não é mais um teste."
-#: ../../app/controllers/plans_controller.rb:449
+#: ../../app/controllers/plans_controller.rb:450
msgid "Unable to change the plan's test status"
msgstr "Não conseguimos mudar o status de teste do plano"
-#: ../../app/controllers/plans_controller.rb:462
+#: ../../app/controllers/plans_controller.rb:463
msgid "There is no plan associated with id %{s"
msgstr "Não há plano associado ao id %{ s"
@@ -779,7 +787,7 @@ msgstr "A senha e a confirmação devem ser iguais"
msgid "research output not found"
msgstr "resultado da pesquisa não encontrado"
-#: ../../app/controllers/roles_controller.rb:26
+#: ../../app/controllers/roles_controller.rb:27
msgid ""
"Cannot share plan with %{email} since that email matches\n"
" with the owner of the plan."
@@ -956,27 +964,27 @@ msgstr "Sua conta foi vinculada a %{scheme}."
msgid "Unable to link your account to %{scheme}."
msgstr "Não é possível vincular sua conta a% {scheme}."
-#: ../../app/controllers/users_controller.rb:149
+#: ../../app/controllers/users_controller.rb:150
msgid "Successfully %{action} %{username}'s account."
msgstr "Successo ao %{action} conta do %{username}"
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "activated"
msgstr "ativado"
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "deactivated"
msgstr "desativado"
-#: ../../app/controllers/users_controller.rb:156
+#: ../../app/controllers/users_controller.rb:157
msgid "Unable to %{action} %{username}"
msgstr "Incapaz de %{action} %{username}"
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "activate"
msgstr "Ativo"
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "deactivate"
msgstr "desativar"
@@ -1268,50 +1276,50 @@ msgstr "Últimos 9 meses"
msgid "Last 12 months"
msgstr "Últimos 12 meses"
-#: ../../app/mailers/user_mailer.rb:17
+#: ../../app/mailers/user_mailer.rb:18
#: ../../app/views/devise/mailer/invitation_instructions.html.erb:5
#: ../../app/views/devise/mailer/reset_password_instructions.html.erb:5
#: ../../app/views/user_mailer/_email_signature.html.erb:2
msgid "Query or feedback related to %{tool_name}"
msgstr "Pergunta ou feedback relacionado a %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:25
+#: ../../app/mailers/user_mailer.rb:26
msgid "Welcome to %{tool_name}"
msgstr "Bem-vindo a %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:62
+#: ../../app/mailers/user_mailer.rb:63
msgid "A Data Management Plan in %{tool_name} has been shared with you"
msgstr "Um plano de gerenciamento de dados em %{tool_name} foi compartilhado com você"
-#: ../../app/mailers/user_mailer.rb:79
+#: ../../app/mailers/user_mailer.rb:80
msgid "Changed permissions on a Data Management Plan in %{tool_name}"
msgstr "Permissões modificadas em um Plano de Gestão de Dados em %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:94
+#: ../../app/mailers/user_mailer.rb:95
msgid "Permissions removed on a DMP in %{tool_name}"
msgstr "Permissões removidas em um PGD em %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:112
+#: ../../app/mailers/user_mailer.rb:113
msgid "%{user_name} has requested feedback on a %{tool_name} plan"
msgstr "%{user_name} solicitou feedback sobre um plano %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:135
+#: ../../app/mailers/user_mailer.rb:136
msgid "%{tool_name}: Expert feedback has been provided for %{plan_title}"
msgstr "%{tool_name}: O feedback de especialistas foi fornecido para %{plan_title}"
-#: ../../app/mailers/user_mailer.rb:153
+#: ../../app/mailers/user_mailer.rb:154
msgid "DMP Visibility Changed: %{plan_title}"
msgstr "Visibilidade do PGD Modificada: %{plan_title}"
-#: ../../app/mailers/user_mailer.rb:182
+#: ../../app/mailers/user_mailer.rb:183
msgid "%{tool_name}: A new comment was added to %{plan_title}"
msgstr "%{tool_name}: Um novo comentário foi adicionado a %{plan_title}"
-#: ../../app/mailers/user_mailer.rb:198
+#: ../../app/mailers/user_mailer.rb:199
msgid "Administrator privileges granted in %{tool_name}"
msgstr "Privilégios de administrador atribuídos em %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:216
+#: ../../app/mailers/user_mailer.rb:217
msgid "%{tool_name} API changes"
msgstr "Alterações na API %{tool_name}"
@@ -1551,15 +1559,15 @@ msgstr ""
msgid "already assigned a value"
msgstr "já atribuiu um valor"
-#: ../../app/models/org.rb:46
+#: ../../app/models/org.rb:47
msgid "Feedback email message"
msgstr "Mensagem de email de feedback"
-#: ../../app/models/org.rb:123
+#: ../../app/models/org.rb:124
msgid "must be one of the following formats: jpeg, jpg, png, gif, bmp"
msgstr "deve ser um dos seguintes formatos: jpeg, jpg, png, gif, bmp"
-#: ../../app/models/org.rb:128
+#: ../../app/models/org.rb:129
msgid "can't be larger than 500KB"
msgstr "não pode ser maior que 500KB"
@@ -1685,7 +1693,7 @@ msgstr "Você não pode publicar um modelo sem perguntas em uma seção."
msgid "Conditions in the template refer backwards"
msgstr "As condições no modelo se referem ao contrário"
-#: ../../app/models/user.rb:380
+#: ../../app/models/user.rb:386
msgid "A Data Management Plan in %{application_name} has been shared with you"
msgstr "Um Plano de Gestão de Dados em %{application_name} foi compartilhado com você"
@@ -2112,7 +2120,7 @@ msgstr ""
#: ../../app/views/paginable/templates/_organisational.html.erb:87
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:29
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:36
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
#: ../../app/views/static_pages/about_us.html.erb:22
#: ../../app/views/static_pages/about_us.html.erb:29
#: ../../app/views/static_pages/termsuse.html.erb:46
@@ -4621,7 +4629,7 @@ msgstr "Comentários e orientações"
msgid "Instructions"
msgstr "Instruções"
-#: ../../app/views/plans/_download_form.html.erb:6
+#: ../../app/views/plans/_download_form.html.erb:5
msgid "Format"
msgstr "Formato"
@@ -4629,71 +4637,71 @@ msgstr "Formato"
msgid "Download settings"
msgstr "Baixar parâmetros"
-#: ../../app/views/plans/_download_form.html.erb:19
-msgid "Select phase to download"
-msgstr "Selecione a fase a ser baixada"
-
-#: ../../app/views/plans/_download_form.html.erb:26
+#: ../../app/views/plans/_download_form.html.erb:21
msgid "Optional plan components"
msgstr "Componentes opcionais do plano"
-#: ../../app/views/plans/_download_form.html.erb:30
+#: ../../app/views/plans/_download_form.html.erb:25
msgid "project details coversheet"
msgstr "capa com detalhes do projeto"
-#: ../../app/views/plans/_download_form.html.erb:36
+#: ../../app/views/plans/_download_form.html.erb:31
msgid "question text and section headings"
msgstr "texto das questões e cabeçalhos das seções"
-#: ../../app/views/plans/_download_form.html.erb:42
+#: ../../app/views/plans/_download_form.html.erb:37
msgid "unanswered questions"
msgstr "questões não respondida"
-#: ../../app/views/plans/_download_form.html.erb:49
+#: ../../app/views/plans/_download_form.html.erb:44
msgid "research outputs"
msgstr "resultados de pesquisa"
-#: ../../app/views/plans/_download_form.html.erb:57
+#: ../../app/views/plans/_download_form.html.erb:52
msgid "supplementary section(s) not requested by funding organisation"
msgstr "seção(ões) suplementar(es) não solicitada(s) pela organização financiadora"
-#: ../../app/views/plans/_download_form.html.erb:65
+#: ../../app/views/plans/_download_form.html.erb:61
+msgid "Select phase to download"
+msgstr "Selecione a fase a ser baixada"
+
+#: ../../app/views/plans/_download_form.html.erb:70
msgid "PDF formatting"
msgstr "Formatação de PDF"
-#: ../../app/views/plans/_download_form.html.erb:68
+#: ../../app/views/plans/_download_form.html.erb:73
msgid "Font"
msgstr "Fonte"
-#: ../../app/views/plans/_download_form.html.erb:71
+#: ../../app/views/plans/_download_form.html.erb:76
msgid "Margin (mm)"
msgstr "Margem (mm)"
-#: ../../app/views/plans/_download_form.html.erb:76
+#: ../../app/views/plans/_download_form.html.erb:81
msgid "Face"
msgstr "Face"
-#: ../../app/views/plans/_download_form.html.erb:84
+#: ../../app/views/plans/_download_form.html.erb:89
msgid "Size"
msgstr "Tamanho"
-#: ../../app/views/plans/_download_form.html.erb:92
+#: ../../app/views/plans/_download_form.html.erb:96
msgid "Top"
msgstr "Alto"
-#: ../../app/views/plans/_download_form.html.erb:101
+#: ../../app/views/plans/_download_form.html.erb:105
msgid "Bottom"
msgstr "Fim da página"
-#: ../../app/views/plans/_download_form.html.erb:110
+#: ../../app/views/plans/_download_form.html.erb:114
msgid "Left"
msgstr "Esquerda"
-#: ../../app/views/plans/_download_form.html.erb:119
+#: ../../app/views/plans/_download_form.html.erb:123
msgid "Right"
msgstr "Direito"
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
msgid ""
"Download Plan (new window)%{open_in_new_window_text}"
diff --git a/config/locale/sv_FI/LC_MESSAGES/app.mo b/config/locale/sv_FI/LC_MESSAGES/app.mo
index 87905cb49b..90d0abe8ae 100644
Binary files a/config/locale/sv_FI/LC_MESSAGES/app.mo and b/config/locale/sv_FI/LC_MESSAGES/app.mo differ
diff --git a/config/locale/sv_FI/app.po b/config/locale/sv_FI/app.po
index 93e28ad899..c464b0683b 100644
--- a/config/locale/sv_FI/app.po
+++ b/config/locale/sv_FI/app.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: roadmap_upstream 1.0\n"
"Report-Msgid-Bugs-To: contact@translation.io\n"
-"POT-Creation-Date: 2025-04-10 13:28-0600\n"
-"PO-Revision-Date: 2025-04-10 21:28+0200\n"
+"POT-Creation-Date: 2025-12-23 08:33-0700\n"
+"PO-Revision-Date: 2025-12-23 15:33+0000\n"
"Last-Translator: FULL NAME \n"
"Language-Team: Swedish\n"
"Language: sv_FI\n"
@@ -127,87 +127,95 @@ msgstr "Ogiltig JSON"
msgid "No Plans found"
msgstr "Inga planer hittades"
-#: ../../app/controllers/application_controller.rb:36
+#: ../../app/controllers/api/v2/base_api_controller.rb:72
+msgid "There was a problem in the server."
+msgstr ""
+
+#: ../../app/controllers/api/v2/base_api_controller.rb:78
+msgid "The client is not authorized to perform this action."
+msgstr ""
+
+#: ../../app/controllers/application_controller.rb:37
msgid "You are not authorized to perform this action."
msgstr "Du har inte behörighet att utföra denna åtgärd."
-#: ../../app/controllers/application_controller.rb:40
+#: ../../app/controllers/application_controller.rb:41
msgid "You need to sign in or sign up before continuing."
msgstr "Du behöver logga in eller registrera dig innan du kan fortsätta."
-#: ../../app/controllers/application_controller.rb:108
+#: ../../app/controllers/application_controller.rb:115
msgid "Unable to %{action} the %{object}. %{errors}"
msgstr "Det går inte att %{action} %{object}. %{errors}"
-#: ../../app/controllers/application_controller.rb:114
+#: ../../app/controllers/application_controller.rb:121
msgid "Successfully %{action} the %{object}."
msgstr "Framgångsrikt %{action} %{object}."
-#: ../../app/controllers/application_controller.rb:127
+#: ../../app/controllers/application_controller.rb:134
msgid "API client"
msgstr "API-klient"
-#: ../../app/controllers/application_controller.rb:128
+#: ../../app/controllers/application_controller.rb:135
msgid "plan"
msgstr "planen"
-#: ../../app/controllers/application_controller.rb:129
+#: ../../app/controllers/application_controller.rb:136
msgid "guidance group"
msgstr "Guidningsgrupp"
-#: ../../app/controllers/application_controller.rb:130
+#: ../../app/controllers/application_controller.rb:137
msgid "comment"
msgstr "Kommentar"
-#: ../../app/controllers/application_controller.rb:131
+#: ../../app/controllers/application_controller.rb:138
msgid "organisation"
msgstr "organisation"
-#: ../../app/controllers/application_controller.rb:132
+#: ../../app/controllers/application_controller.rb:139
msgid "permission"
msgstr "lov"
-#: ../../app/controllers/application_controller.rb:133
+#: ../../app/controllers/application_controller.rb:140
msgid "preferences"
msgstr "preferenser"
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "profile"
msgstr "profil"
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "user"
msgstr "användare"
-#: ../../app/controllers/application_controller.rb:135
+#: ../../app/controllers/application_controller.rb:142
msgid "question option"
msgstr "fråga alternativ"
-#: ../../app/controllers/application_controller.rb:181
+#: ../../app/controllers/application_controller.rb:188
msgid "Record Not Found"
msgstr "Posten hittades inte"
-#: ../../app/controllers/concerns/paginable.rb:45
+#: ../../app/controllers/concerns/paginable.rb:46
msgid "scope should be an ActiveRecord::Relation object"
msgstr "Räckvidd bör vara ett ActiveRecord :: Relation-objekt"
-#: ../../app/controllers/concerns/paginable.rb:47
+#: ../../app/controllers/concerns/paginable.rb:48
msgid "path_params should be a Hash object"
msgstr "path_params ska vara ett Hash-objekt"
-#: ../../app/controllers/concerns/paginable.rb:48
+#: ../../app/controllers/concerns/paginable.rb:49
msgid "query_params should be a Hash object"
msgstr "query_params ska vara ett Hash-objekt"
-#: ../../app/controllers/concerns/paginable.rb:49
+#: ../../app/controllers/concerns/paginable.rb:50
msgid "locals should be a Hash object"
msgstr "lokalbefolkningen borde vara ett Hash-objekt"
-#: ../../app/controllers/concerns/paginable.rb:70
+#: ../../app/controllers/concerns/paginable.rb:71
msgid "Restricted access to View All the records"
msgstr "Begränsad åtkomst till Visa alla poster"
-#: ../../app/controllers/concerns/paginable.rb:183
+#: ../../app/controllers/concerns/paginable.rb:184
msgid "Sort by %{sort_field}"
msgstr "Sortera efter %{sort_field}"
@@ -248,77 +256,77 @@ msgstr "Kontaktadressen skickades med framgång."
msgid "Unable to submit your request"
msgstr "Det gick inte att skicka din förfrågan"
-#: ../../app/controllers/contributors_controller.rb:40
-#: ../../app/controllers/contributors_controller.rb:56
+#: ../../app/controllers/contributors_controller.rb:41
+#: ../../app/controllers/contributors_controller.rb:57
#: ../../app/controllers/research_outputs_controller.rb:42
msgid "add"
msgstr "Lägg till"
-#: ../../app/controllers/contributors_controller.rb:54
+#: ../../app/controllers/contributors_controller.rb:55
#: ../../app/controllers/research_outputs_controller.rb:40
msgid "added"
msgstr "Lagt till"
-#: ../../app/controllers/contributors_controller.rb:72
+#: ../../app/controllers/contributors_controller.rb:73
#: ../../app/controllers/guidance_groups_controller.rb:55
#: ../../app/controllers/guidances_controller.rb:75
-#: ../../app/controllers/notes_controller.rb:88
+#: ../../app/controllers/notes_controller.rb:89
#: ../../app/controllers/org_admin/departments_controller.rb:50
#: ../../app/controllers/org_admin/sections_controller.rb:103
#: ../../app/controllers/org_admin/templates_controller.rb:210
#: ../../app/controllers/orgs_controller.rb:92
-#: ../../app/controllers/plans_controller.rb:280
-#: ../../app/controllers/plans_controller.rb:283
+#: ../../app/controllers/plans_controller.rb:281
+#: ../../app/controllers/plans_controller.rb:284
#: ../../app/controllers/registrations_controller.rb:249
#: ../../app/controllers/registrations_controller.rb:253
#: ../../app/controllers/registrations_controller.rb:280
#: ../../app/controllers/registrations_controller.rb:284
#: ../../app/controllers/research_outputs_controller.rb:60
-#: ../../app/controllers/users_controller.rb:103
-#: ../../app/controllers/users_controller.rb:131
+#: ../../app/controllers/users_controller.rb:104
+#: ../../app/controllers/users_controller.rb:132
msgid "saved"
msgstr "sparade"
-#: ../../app/controllers/contributors_controller.rb:74
+#: ../../app/controllers/contributors_controller.rb:75
#: ../../app/controllers/guidance_groups_controller.rb:57
#: ../../app/controllers/guidances_controller.rb:77
-#: ../../app/controllers/notes_controller.rb:106
+#: ../../app/controllers/notes_controller.rb:107
#: ../../app/controllers/org_admin/departments_controller.rb:52
#: ../../app/controllers/org_admin/sections_controller.rb:105
#: ../../app/controllers/org_admin/templates_controller.rb:215
#: ../../app/controllers/orgs_controller.rb:94
-#: ../../app/controllers/plans_controller.rb:289
-#: ../../app/controllers/plans_controller.rb:292
-#: ../../app/controllers/plans_controller.rb:296
-#: ../../app/controllers/plans_controller.rb:299
+#: ../../app/controllers/plans_controller.rb:290
+#: ../../app/controllers/plans_controller.rb:293
+#: ../../app/controllers/plans_controller.rb:297
+#: ../../app/controllers/plans_controller.rb:300
#: ../../app/controllers/registrations_controller.rb:256
#: ../../app/controllers/registrations_controller.rb:287
#: ../../app/controllers/research_outputs_controller.rb:63
msgid "save"
msgstr "spara"
-#: ../../app/controllers/contributors_controller.rb:83
-#: ../../app/controllers/notes_controller.rb:130
+#: ../../app/controllers/contributors_controller.rb:84
+#: ../../app/controllers/notes_controller.rb:131
#: ../../app/controllers/org_admin/templates_controller.rb:243
#: ../../app/controllers/research_outputs_controller.rb:74
#: ../../app/controllers/super_admin/orgs_controller.rb:94
msgid "removed"
msgstr "tog bort"
-#: ../../app/controllers/contributors_controller.rb:86
-#: ../../app/controllers/notes_controller.rb:148
+#: ../../app/controllers/contributors_controller.rb:87
+#: ../../app/controllers/notes_controller.rb:149
#: ../../app/controllers/org_admin/templates_controller.rb:245
#: ../../app/controllers/research_outputs_controller.rb:77
#: ../../app/controllers/super_admin/orgs_controller.rb:97
msgid "remove"
msgstr "ta bort"
-#: ../../app/controllers/contributors_controller.rb:160
+#: ../../app/controllers/contributors_controller.rb:161
#: ../../app/controllers/research_outputs_controller.rb:208
msgid "plan not found"
msgstr "Planen hittades inte"
-#: ../../app/controllers/contributors_controller.rb:168
+#: ../../app/controllers/contributors_controller.rb:169
msgid "contributor not found"
msgstr "bidragsgivare hittades inte"
@@ -332,7 +340,7 @@ msgstr "Ett fel uppstod när du begärde feedback för den här planen."
#: ../../app/controllers/guidance_groups_controller.rb:31
#: ../../app/controllers/guidances_controller.rb:53
-#: ../../app/controllers/notes_controller.rb:47
+#: ../../app/controllers/notes_controller.rb:48
#: ../../app/controllers/org_admin/departments_controller.rb:26
#: ../../app/controllers/org_admin/phases_controller.rb:121
#: ../../app/controllers/org_admin/questions_controller.rb:94
@@ -348,7 +356,7 @@ msgstr "skapad"
#: ../../app/controllers/guidance_groups_controller.rb:34
#: ../../app/controllers/guidances_controller.rb:55
-#: ../../app/controllers/notes_controller.rb:66
+#: ../../app/controllers/notes_controller.rb:67
#: ../../app/controllers/org_admin/departments_controller.rb:30
#: ../../app/controllers/org_admin/phases_controller.rb:123
#: ../../app/controllers/org_admin/questions_controller.rb:96
@@ -389,7 +397,7 @@ msgstr "Avpublicera"
#: ../../app/controllers/org_admin/question_options_controller.rb:24
#: ../../app/controllers/org_admin/questions_controller.rb:197
#: ../../app/controllers/org_admin/sections_controller.rb:128
-#: ../../app/controllers/plans_controller.rb:342
+#: ../../app/controllers/plans_controller.rb:343
#: ../../app/controllers/super_admin/api_clients_controller.rb:81
#: ../../app/controllers/super_admin/notifications_controller.rb:85
#: ../../app/controllers/super_admin/themes_controller.rb:51
@@ -403,7 +411,7 @@ msgstr "raderade"
#: ../../app/controllers/org_admin/question_options_controller.rb:26
#: ../../app/controllers/org_admin/questions_controller.rb:199
#: ../../app/controllers/org_admin/sections_controller.rb:130
-#: ../../app/controllers/plans_controller.rb:347
+#: ../../app/controllers/plans_controller.rb:348
#: ../../app/controllers/super_admin/api_clients_controller.rb:84
#: ../../app/controllers/super_admin/notifications_controller.rb:88
#: ../../app/controllers/super_admin/themes_controller.rb:54
@@ -448,19 +456,19 @@ msgstr "Det gick inte att skapa en ny version av den här mallen.
"
#: ../../app/controllers/org_admin/phases_controller.rb:147
#: ../../app/controllers/org_admin/questions_controller.rb:166
#: ../../app/controllers/org_admin/users_controller.rb:30
-#: ../../app/controllers/plans_controller.rb:416
+#: ../../app/controllers/plans_controller.rb:417
#: ../../app/controllers/super_admin/api_clients_controller.rb:68
#: ../../app/controllers/super_admin/notifications_controller.rb:52
#: ../../app/controllers/super_admin/themes_controller.rb:39
#: ../../app/controllers/super_admin/users_controller.rb:54
-#: ../../app/controllers/users_controller.rb:108
+#: ../../app/controllers/users_controller.rb:109
msgid "updated"
msgstr "Uppdaterad"
#: ../../app/controllers/org_admin/phases_controller.rb:149
#: ../../app/controllers/org_admin/questions_controller.rb:169
#: ../../app/controllers/org_admin/users_controller.rb:32
-#: ../../app/controllers/plans_controller.rb:419
+#: ../../app/controllers/plans_controller.rb:420
#: ../../app/controllers/super_admin/api_clients_controller.rb:70
#: ../../app/controllers/super_admin/notifications_controller.rb:55
#: ../../app/controllers/super_admin/themes_controller.rb:41
@@ -550,7 +558,7 @@ msgid "Unable to delete this version of the template."
msgstr "Det gick inte att ta bort den här versionen av mallen."
#: ../../app/controllers/org_admin/template_copies_controller.rb:20
-#: ../../app/controllers/plans_controller.rb:395
+#: ../../app/controllers/plans_controller.rb:396
msgid "copy"
msgstr "kopia"
@@ -559,11 +567,11 @@ msgstr "kopia"
msgid "That template is no longer customizable."
msgstr "Den mallen är inte längre anpassningsbar."
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:21
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:22
msgid "Unable to customize that template."
msgstr "Det gick inte att anpassa den mallen."
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:24
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:25
msgid "That template is not customizable."
msgstr "Den mallen är inte anpassningsbar."
@@ -653,11 +661,11 @@ msgstr "Denna plan är baserad på"
msgid "template with customisations by the"
msgstr "mall med anpassningar av"
-#: ../../app/controllers/plans_controller.rb:393
+#: ../../app/controllers/plans_controller.rb:394
msgid "copied"
msgstr "kopieras"
-#: ../../app/controllers/plans_controller.rb:424
+#: ../../app/controllers/plans_controller.rb:425
msgid ""
"Unable to change the plan's status since it is needed at least %{percentage} p"
"ercentage responded"
@@ -665,23 +673,23 @@ msgstr ""
"Det går inte att ändra planens status eftersom det behövs minst %{percentage} "
"procent svarat"
-#: ../../app/controllers/plans_controller.rb:430
+#: ../../app/controllers/plans_controller.rb:431
msgid "Unable to find plan id %{plan_id}"
msgstr "Det gick inte att hitta plan id %{plan_id}"
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is now a test."
msgstr "Ditt projekt är nu ett test."
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is no longer a test."
msgstr "Ditt projekt är inte längre ett test."
-#: ../../app/controllers/plans_controller.rb:449
+#: ../../app/controllers/plans_controller.rb:450
msgid "Unable to change the plan's test status"
msgstr "Kan inte ändra planens teststatus"
-#: ../../app/controllers/plans_controller.rb:462
+#: ../../app/controllers/plans_controller.rb:463
msgid "There is no plan associated with id %{s"
msgstr "Det finns ingen plan kopplad till id %{ s"
@@ -775,7 +783,7 @@ msgstr "Lösenord och bekräftelse måste matcha"
msgid "research output not found"
msgstr "forskningsresultat hittades inte"
-#: ../../app/controllers/roles_controller.rb:26
+#: ../../app/controllers/roles_controller.rb:27
msgid ""
"Cannot share plan with %{email} since that email matches\n"
" with the owner of the plan."
@@ -948,27 +956,27 @@ msgstr "Ditt konto har länkats till %{scheme}."
msgid "Unable to link your account to %{scheme}."
msgstr "Det gick inte att länka ditt konto till %{scheme}."
-#: ../../app/controllers/users_controller.rb:149
+#: ../../app/controllers/users_controller.rb:150
msgid "Successfully %{action} %{username}'s account."
msgstr "Framgångsrikt %{action} %{username} s konto."
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "activated"
msgstr "aktiverad"
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "deactivated"
msgstr "deaktiveras"
-#: ../../app/controllers/users_controller.rb:156
+#: ../../app/controllers/users_controller.rb:157
msgid "Unable to %{action} %{username}"
msgstr "Kan inte %{action} %{username}"
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "activate"
msgstr "Aktivera"
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "deactivate"
msgstr "avaktivera"
@@ -1259,50 +1267,50 @@ msgstr "Senaste 9 månaderna"
msgid "Last 12 months"
msgstr "Senaste 12 månaderna"
-#: ../../app/mailers/user_mailer.rb:17
+#: ../../app/mailers/user_mailer.rb:18
#: ../../app/views/devise/mailer/invitation_instructions.html.erb:5
#: ../../app/views/devise/mailer/reset_password_instructions.html.erb:5
#: ../../app/views/user_mailer/_email_signature.html.erb:2
msgid "Query or feedback related to %{tool_name}"
msgstr "Fråga eller feedback relaterad till %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:25
+#: ../../app/mailers/user_mailer.rb:26
msgid "Welcome to %{tool_name}"
msgstr "Välkommen till %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:62
+#: ../../app/mailers/user_mailer.rb:63
msgid "A Data Management Plan in %{tool_name} has been shared with you"
msgstr "En datahanteringsplan i %{tool_name} har delats med dig"
-#: ../../app/mailers/user_mailer.rb:79
+#: ../../app/mailers/user_mailer.rb:80
msgid "Changed permissions on a Data Management Plan in %{tool_name}"
msgstr "Ändrade behörigheter på en datahanteringsplan i %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:94
+#: ../../app/mailers/user_mailer.rb:95
msgid "Permissions removed on a DMP in %{tool_name}"
msgstr "Behörigheter tas bort på en DMP i %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:112
+#: ../../app/mailers/user_mailer.rb:113
msgid "%{user_name} has requested feedback on a %{tool_name} plan"
msgstr "%{user_name} har begärt feedback på en %{tool_name} plan"
-#: ../../app/mailers/user_mailer.rb:135
+#: ../../app/mailers/user_mailer.rb:136
msgid "%{tool_name}: Expert feedback has been provided for %{plan_title}"
msgstr "%{tool_name}: Feedback från experter har lämnats för %{plan_title}"
-#: ../../app/mailers/user_mailer.rb:153
+#: ../../app/mailers/user_mailer.rb:154
msgid "DMP Visibility Changed: %{plan_title}"
msgstr "DMP-synlighet ändrad: %{plan_title}"
-#: ../../app/mailers/user_mailer.rb:182
+#: ../../app/mailers/user_mailer.rb:183
msgid "%{tool_name}: A new comment was added to %{plan_title}"
msgstr "%{tool_name}: En ny kommentar läggs till i %{plan_title}"
-#: ../../app/mailers/user_mailer.rb:198
+#: ../../app/mailers/user_mailer.rb:199
msgid "Administrator privileges granted in %{tool_name}"
msgstr "Administratörsbehörighet beviljas i %{tool_name}"
-#: ../../app/mailers/user_mailer.rb:216
+#: ../../app/mailers/user_mailer.rb:217
msgid "%{tool_name} API changes"
msgstr "%{tool_name} API-ändringar"
@@ -1542,15 +1550,15 @@ msgstr ""
msgid "already assigned a value"
msgstr "redan tilldelat ett värde"
-#: ../../app/models/org.rb:46
+#: ../../app/models/org.rb:47
msgid "Feedback email message"
msgstr "Feedback e-postmeddelande"
-#: ../../app/models/org.rb:123
+#: ../../app/models/org.rb:124
msgid "must be one of the following formats: jpeg, jpg, png, gif, bmp"
msgstr "måste vara ett av följande format: jpeg, jpg, png, gif, bmp"
-#: ../../app/models/org.rb:128
+#: ../../app/models/org.rb:129
msgid "can't be larger than 500KB"
msgstr "kan inte vara större än 500 kB"
@@ -1674,7 +1682,7 @@ msgstr "Du kan inte publicera en mall utan frågor i en sektion."
msgid "Conditions in the template refer backwards"
msgstr "Förhållandena i mallen hänvisar bakåt"
-#: ../../app/models/user.rb:380
+#: ../../app/models/user.rb:386
msgid "A Data Management Plan in %{application_name} has been shared with you"
msgstr "En datahanteringsplan i %{application_name} har delats med dig"
@@ -2101,7 +2109,7 @@ msgstr ""
#: ../../app/views/paginable/templates/_organisational.html.erb:87
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:29
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:36
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
#: ../../app/views/static_pages/about_us.html.erb:22
#: ../../app/views/static_pages/about_us.html.erb:29
#: ../../app/views/static_pages/termsuse.html.erb:46
@@ -4595,7 +4603,7 @@ msgstr "Kommentarer & vägledning"
msgid "Instructions"
msgstr "Instruktioner"
-#: ../../app/views/plans/_download_form.html.erb:6
+#: ../../app/views/plans/_download_form.html.erb:5
msgid "Format"
msgstr "Formatera"
@@ -4603,71 +4611,71 @@ msgstr "Formatera"
msgid "Download settings"
msgstr "Hämta inställningar"
-#: ../../app/views/plans/_download_form.html.erb:19
-msgid "Select phase to download"
-msgstr "Välj fas att hämta"
-
-#: ../../app/views/plans/_download_form.html.erb:26
+#: ../../app/views/plans/_download_form.html.erb:21
msgid "Optional plan components"
msgstr "Valfria plankomponenter"
-#: ../../app/views/plans/_download_form.html.erb:30
+#: ../../app/views/plans/_download_form.html.erb:25
msgid "project details coversheet"
msgstr "projekt detaljer täckplåt"
-#: ../../app/views/plans/_download_form.html.erb:36
+#: ../../app/views/plans/_download_form.html.erb:31
msgid "question text and section headings"
msgstr "Frågeformulär och rubrikrubriker"
-#: ../../app/views/plans/_download_form.html.erb:42
+#: ../../app/views/plans/_download_form.html.erb:37
msgid "unanswered questions"
msgstr "obesvarade frågor"
-#: ../../app/views/plans/_download_form.html.erb:49
+#: ../../app/views/plans/_download_form.html.erb:44
msgid "research outputs"
msgstr "forskningsresultat"
-#: ../../app/views/plans/_download_form.html.erb:57
+#: ../../app/views/plans/_download_form.html.erb:52
msgid "supplementary section(s) not requested by funding organisation"
msgstr "kompletterande sektion (er) som inte begärs av finansieringsorganisationen"
-#: ../../app/views/plans/_download_form.html.erb:65
+#: ../../app/views/plans/_download_form.html.erb:61
+msgid "Select phase to download"
+msgstr "Välj fas att hämta"
+
+#: ../../app/views/plans/_download_form.html.erb:70
msgid "PDF formatting"
msgstr "PDF-formatering"
-#: ../../app/views/plans/_download_form.html.erb:68
+#: ../../app/views/plans/_download_form.html.erb:73
msgid "Font"
msgstr "Font"
-#: ../../app/views/plans/_download_form.html.erb:71
+#: ../../app/views/plans/_download_form.html.erb:76
msgid "Margin (mm)"
msgstr "Marginal (mm)"
-#: ../../app/views/plans/_download_form.html.erb:76
+#: ../../app/views/plans/_download_form.html.erb:81
msgid "Face"
msgstr "Ansikte"
-#: ../../app/views/plans/_download_form.html.erb:84
+#: ../../app/views/plans/_download_form.html.erb:89
msgid "Size"
msgstr "Storlek"
-#: ../../app/views/plans/_download_form.html.erb:92
+#: ../../app/views/plans/_download_form.html.erb:96
msgid "Top"
msgstr "Topp"
-#: ../../app/views/plans/_download_form.html.erb:101
+#: ../../app/views/plans/_download_form.html.erb:105
msgid "Bottom"
msgstr "Botten"
-#: ../../app/views/plans/_download_form.html.erb:110
+#: ../../app/views/plans/_download_form.html.erb:114
msgid "Left"
msgstr "Vänster"
-#: ../../app/views/plans/_download_form.html.erb:119
+#: ../../app/views/plans/_download_form.html.erb:123
msgid "Right"
msgstr "Höger"
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
msgid ""
"Download Plan (new window)%{open_in_new_window_text}"
diff --git a/config/locale/tr_TR/LC_MESSAGES/app.mo b/config/locale/tr_TR/LC_MESSAGES/app.mo
index 771cc90b3d..147db98432 100644
Binary files a/config/locale/tr_TR/LC_MESSAGES/app.mo and b/config/locale/tr_TR/LC_MESSAGES/app.mo differ
diff --git a/config/locale/tr_TR/app.po b/config/locale/tr_TR/app.po
index 184aef913c..439e806db9 100644
--- a/config/locale/tr_TR/app.po
+++ b/config/locale/tr_TR/app.po
@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: roadmap_upstream 1.0\n"
"Report-Msgid-Bugs-To: contact@translation.io\n"
-"POT-Creation-Date: 2025-04-10 13:28-0600\n"
-"PO-Revision-Date: 2025-04-10 21:28+0200\n"
+"POT-Creation-Date: 2025-12-23 08:33-0700\n"
+"PO-Revision-Date: 2025-12-23 15:33+0000\n"
"Last-Translator: FULL NAME \n"
"Language-Team: Turkish\n"
"Language: tr_TR\n"
@@ -125,87 +125,95 @@ msgstr "Geçersiz JSON"
msgid "No Plans found"
msgstr "Hiç Plan bulunamadı"
-#: ../../app/controllers/application_controller.rb:36
+#: ../../app/controllers/api/v2/base_api_controller.rb:72
+msgid "There was a problem in the server."
+msgstr ""
+
+#: ../../app/controllers/api/v2/base_api_controller.rb:78
+msgid "The client is not authorized to perform this action."
+msgstr ""
+
+#: ../../app/controllers/application_controller.rb:37
msgid "You are not authorized to perform this action."
msgstr "Bu eylemi gerçekleştirme yetkiniz yok."
-#: ../../app/controllers/application_controller.rb:40
+#: ../../app/controllers/application_controller.rb:41
msgid "You need to sign in or sign up before continuing."
msgstr "Devam etmeden önce oturum açmanız veya kaydolmanız gerekir."
-#: ../../app/controllers/application_controller.rb:108
+#: ../../app/controllers/application_controller.rb:115
msgid "Unable to %{action} the %{object}. %{errors}"
msgstr "%{action} %{object} yapılamıyor. %{errors}"
-#: ../../app/controllers/application_controller.rb:114
+#: ../../app/controllers/application_controller.rb:121
msgid "Successfully %{action} the %{object}."
msgstr "%{object} başarıyla %{action}."
-#: ../../app/controllers/application_controller.rb:127
+#: ../../app/controllers/application_controller.rb:134
msgid "API client"
msgstr "API istemcisi"
-#: ../../app/controllers/application_controller.rb:128
+#: ../../app/controllers/application_controller.rb:135
msgid "plan"
msgstr "plan"
-#: ../../app/controllers/application_controller.rb:129
+#: ../../app/controllers/application_controller.rb:136
msgid "guidance group"
msgstr "rehberlik grubu"
-#: ../../app/controllers/application_controller.rb:130
+#: ../../app/controllers/application_controller.rb:137
msgid "comment"
msgstr "yorum yap"
-#: ../../app/controllers/application_controller.rb:131
+#: ../../app/controllers/application_controller.rb:138
msgid "organisation"
msgstr "kuruluş"
-#: ../../app/controllers/application_controller.rb:132
+#: ../../app/controllers/application_controller.rb:139
msgid "permission"
msgstr "izin"
-#: ../../app/controllers/application_controller.rb:133
+#: ../../app/controllers/application_controller.rb:140
msgid "preferences"
msgstr "tercihler"
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "profile"
msgstr "profil"
-#: ../../app/controllers/application_controller.rb:134
+#: ../../app/controllers/application_controller.rb:141
msgid "user"
msgstr "kullanıcı"
-#: ../../app/controllers/application_controller.rb:135
+#: ../../app/controllers/application_controller.rb:142
msgid "question option"
msgstr "soru seçeneği"
-#: ../../app/controllers/application_controller.rb:181
+#: ../../app/controllers/application_controller.rb:188
msgid "Record Not Found"
msgstr "Kayıt bulunamadı"
-#: ../../app/controllers/concerns/paginable.rb:45
+#: ../../app/controllers/concerns/paginable.rb:46
msgid "scope should be an ActiveRecord::Relation object"
msgstr "kapsam bir ActiveRecord::Relation nesnesi olmalıdır"
-#: ../../app/controllers/concerns/paginable.rb:47
+#: ../../app/controllers/concerns/paginable.rb:48
msgid "path_params should be a Hash object"
msgstr "path_params bir Hash nesnesi olmalıdır"
-#: ../../app/controllers/concerns/paginable.rb:48
+#: ../../app/controllers/concerns/paginable.rb:49
msgid "query_params should be a Hash object"
msgstr "query_params bir Hash nesnesi olmalıdır"
-#: ../../app/controllers/concerns/paginable.rb:49
+#: ../../app/controllers/concerns/paginable.rb:50
msgid "locals should be a Hash object"
msgstr "locals bir Hash nesnesi olmalıdır"
-#: ../../app/controllers/concerns/paginable.rb:70
+#: ../../app/controllers/concerns/paginable.rb:71
msgid "Restricted access to View All the records"
msgstr "Tüm kayıtları görüntülemek için kısıtlı erişim"
-#: ../../app/controllers/concerns/paginable.rb:183
+#: ../../app/controllers/concerns/paginable.rb:184
msgid "Sort by %{sort_field}"
msgstr "%{sort_field} alanına göre sırala"
@@ -246,77 +254,77 @@ msgstr "İletişim e-postası başarıyla gönderildi."
msgid "Unable to submit your request"
msgstr "İsteğiniz gönderilemedi"
-#: ../../app/controllers/contributors_controller.rb:40
-#: ../../app/controllers/contributors_controller.rb:56
+#: ../../app/controllers/contributors_controller.rb:41
+#: ../../app/controllers/contributors_controller.rb:57
#: ../../app/controllers/research_outputs_controller.rb:42
msgid "add"
msgstr "ekle"
-#: ../../app/controllers/contributors_controller.rb:54
+#: ../../app/controllers/contributors_controller.rb:55
#: ../../app/controllers/research_outputs_controller.rb:40
msgid "added"
msgstr "eklendi"
-#: ../../app/controllers/contributors_controller.rb:72
+#: ../../app/controllers/contributors_controller.rb:73
#: ../../app/controllers/guidance_groups_controller.rb:55
#: ../../app/controllers/guidances_controller.rb:75
-#: ../../app/controllers/notes_controller.rb:88
+#: ../../app/controllers/notes_controller.rb:89
#: ../../app/controllers/org_admin/departments_controller.rb:50
#: ../../app/controllers/org_admin/sections_controller.rb:103
#: ../../app/controllers/org_admin/templates_controller.rb:210
#: ../../app/controllers/orgs_controller.rb:92
-#: ../../app/controllers/plans_controller.rb:280
-#: ../../app/controllers/plans_controller.rb:283
+#: ../../app/controllers/plans_controller.rb:281
+#: ../../app/controllers/plans_controller.rb:284
#: ../../app/controllers/registrations_controller.rb:249
#: ../../app/controllers/registrations_controller.rb:253
#: ../../app/controllers/registrations_controller.rb:280
#: ../../app/controllers/registrations_controller.rb:284
#: ../../app/controllers/research_outputs_controller.rb:60
-#: ../../app/controllers/users_controller.rb:103
-#: ../../app/controllers/users_controller.rb:131
+#: ../../app/controllers/users_controller.rb:104
+#: ../../app/controllers/users_controller.rb:132
msgid "saved"
msgstr "kaydedildi"
-#: ../../app/controllers/contributors_controller.rb:74
+#: ../../app/controllers/contributors_controller.rb:75
#: ../../app/controllers/guidance_groups_controller.rb:57
#: ../../app/controllers/guidances_controller.rb:77
-#: ../../app/controllers/notes_controller.rb:106
+#: ../../app/controllers/notes_controller.rb:107
#: ../../app/controllers/org_admin/departments_controller.rb:52
#: ../../app/controllers/org_admin/sections_controller.rb:105
#: ../../app/controllers/org_admin/templates_controller.rb:215
#: ../../app/controllers/orgs_controller.rb:94
-#: ../../app/controllers/plans_controller.rb:289
-#: ../../app/controllers/plans_controller.rb:292
-#: ../../app/controllers/plans_controller.rb:296
-#: ../../app/controllers/plans_controller.rb:299
+#: ../../app/controllers/plans_controller.rb:290
+#: ../../app/controllers/plans_controller.rb:293
+#: ../../app/controllers/plans_controller.rb:297
+#: ../../app/controllers/plans_controller.rb:300
#: ../../app/controllers/registrations_controller.rb:256
#: ../../app/controllers/registrations_controller.rb:287
#: ../../app/controllers/research_outputs_controller.rb:63
msgid "save"
msgstr "kaydet"
-#: ../../app/controllers/contributors_controller.rb:83
-#: ../../app/controllers/notes_controller.rb:130
+#: ../../app/controllers/contributors_controller.rb:84
+#: ../../app/controllers/notes_controller.rb:131
#: ../../app/controllers/org_admin/templates_controller.rb:243
#: ../../app/controllers/research_outputs_controller.rb:74
#: ../../app/controllers/super_admin/orgs_controller.rb:94
msgid "removed"
msgstr "kaldırıldı"
-#: ../../app/controllers/contributors_controller.rb:86
-#: ../../app/controllers/notes_controller.rb:148
+#: ../../app/controllers/contributors_controller.rb:87
+#: ../../app/controllers/notes_controller.rb:149
#: ../../app/controllers/org_admin/templates_controller.rb:245
#: ../../app/controllers/research_outputs_controller.rb:77
#: ../../app/controllers/super_admin/orgs_controller.rb:97
msgid "remove"
msgstr "kaldır"
-#: ../../app/controllers/contributors_controller.rb:160
+#: ../../app/controllers/contributors_controller.rb:161
#: ../../app/controllers/research_outputs_controller.rb:208
msgid "plan not found"
msgstr "plan bulunamadı"
-#: ../../app/controllers/contributors_controller.rb:168
+#: ../../app/controllers/contributors_controller.rb:169
msgid "contributor not found"
msgstr "katkı sağlayan kişi bulunamadı"
@@ -330,7 +338,7 @@ msgstr "Bu plan için geri bildirim istenirken bir hata oluştu."
#: ../../app/controllers/guidance_groups_controller.rb:31
#: ../../app/controllers/guidances_controller.rb:53
-#: ../../app/controllers/notes_controller.rb:47
+#: ../../app/controllers/notes_controller.rb:48
#: ../../app/controllers/org_admin/departments_controller.rb:26
#: ../../app/controllers/org_admin/phases_controller.rb:121
#: ../../app/controllers/org_admin/questions_controller.rb:94
@@ -346,7 +354,7 @@ msgstr "oluşturuldu"
#: ../../app/controllers/guidance_groups_controller.rb:34
#: ../../app/controllers/guidances_controller.rb:55
-#: ../../app/controllers/notes_controller.rb:66
+#: ../../app/controllers/notes_controller.rb:67
#: ../../app/controllers/org_admin/departments_controller.rb:30
#: ../../app/controllers/org_admin/phases_controller.rb:123
#: ../../app/controllers/org_admin/questions_controller.rb:96
@@ -385,7 +393,7 @@ msgstr "yayından kaldır"
#: ../../app/controllers/org_admin/question_options_controller.rb:24
#: ../../app/controllers/org_admin/questions_controller.rb:197
#: ../../app/controllers/org_admin/sections_controller.rb:128
-#: ../../app/controllers/plans_controller.rb:342
+#: ../../app/controllers/plans_controller.rb:343
#: ../../app/controllers/super_admin/api_clients_controller.rb:81
#: ../../app/controllers/super_admin/notifications_controller.rb:85
#: ../../app/controllers/super_admin/themes_controller.rb:51
@@ -399,7 +407,7 @@ msgstr "silindi"
#: ../../app/controllers/org_admin/question_options_controller.rb:26
#: ../../app/controllers/org_admin/questions_controller.rb:199
#: ../../app/controllers/org_admin/sections_controller.rb:130
-#: ../../app/controllers/plans_controller.rb:347
+#: ../../app/controllers/plans_controller.rb:348
#: ../../app/controllers/super_admin/api_clients_controller.rb:84
#: ../../app/controllers/super_admin/notifications_controller.rb:88
#: ../../app/controllers/super_admin/themes_controller.rb:54
@@ -442,19 +450,19 @@ msgstr "Bu şablonun yeni bir sürümü oluşturulamıyor.
"
#: ../../app/controllers/org_admin/phases_controller.rb:147
#: ../../app/controllers/org_admin/questions_controller.rb:166
#: ../../app/controllers/org_admin/users_controller.rb:30
-#: ../../app/controllers/plans_controller.rb:416
+#: ../../app/controllers/plans_controller.rb:417
#: ../../app/controllers/super_admin/api_clients_controller.rb:68
#: ../../app/controllers/super_admin/notifications_controller.rb:52
#: ../../app/controllers/super_admin/themes_controller.rb:39
#: ../../app/controllers/super_admin/users_controller.rb:54
-#: ../../app/controllers/users_controller.rb:108
+#: ../../app/controllers/users_controller.rb:109
msgid "updated"
msgstr "güncellendi"
#: ../../app/controllers/org_admin/phases_controller.rb:149
#: ../../app/controllers/org_admin/questions_controller.rb:169
#: ../../app/controllers/org_admin/users_controller.rb:32
-#: ../../app/controllers/plans_controller.rb:419
+#: ../../app/controllers/plans_controller.rb:420
#: ../../app/controllers/super_admin/api_clients_controller.rb:70
#: ../../app/controllers/super_admin/notifications_controller.rb:55
#: ../../app/controllers/super_admin/themes_controller.rb:41
@@ -544,7 +552,7 @@ msgid "Unable to delete this version of the template."
msgstr "Şablonun bu sürümü silinemiyor."
#: ../../app/controllers/org_admin/template_copies_controller.rb:20
-#: ../../app/controllers/plans_controller.rb:395
+#: ../../app/controllers/plans_controller.rb:396
msgid "copy"
msgstr "kopyala"
@@ -553,11 +561,11 @@ msgstr "kopyala"
msgid "That template is no longer customizable."
msgstr "Bu şablon artık özelleştirilemez."
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:21
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:22
msgid "Unable to customize that template."
msgstr "Bu şablon özelleştirilemiyor."
-#: ../../app/controllers/org_admin/template_customizations_controller.rb:24
+#: ../../app/controllers/org_admin/template_customizations_controller.rb:25
msgid "That template is not customizable."
msgstr "Bu şablon özelleştirilemez."
@@ -649,11 +657,11 @@ msgstr "Bu plan şunlara dayanmaktadır:"
msgid "template with customisations by the"
msgstr "şu kişi tarafından özelleştirmeler içeren şablon:"
-#: ../../app/controllers/plans_controller.rb:393
+#: ../../app/controllers/plans_controller.rb:394
msgid "copied"
msgstr "kopyalandı"
-#: ../../app/controllers/plans_controller.rb:424
+#: ../../app/controllers/plans_controller.rb:425
msgid ""
"Unable to change the plan's status since it is needed at least %{percentage} p"
"ercentage responded"
@@ -661,23 +669,23 @@ msgstr ""
"En az yüzde %{percentage} yanıt verilmesi gerektiğinden planın durumu değiştir"
"ilemiyor"
-#: ../../app/controllers/plans_controller.rb:430
+#: ../../app/controllers/plans_controller.rb:431
msgid "Unable to find plan id %{plan_id}"
msgstr "%{plan_id} no.'lu plan bulunamadı"
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is now a test."
msgstr "Projeniz şu an bir test."
-#: ../../app/controllers/plans_controller.rb:445
+#: ../../app/controllers/plans_controller.rb:446
msgid "Your project is no longer a test."
msgstr "Projeniz artık bir test değil."
-#: ../../app/controllers/plans_controller.rb:449
+#: ../../app/controllers/plans_controller.rb:450
msgid "Unable to change the plan's test status"
msgstr "Planın test durumu değiştirilemiyor"
-#: ../../app/controllers/plans_controller.rb:462
+#: ../../app/controllers/plans_controller.rb:463
msgid "There is no plan associated with id %{s"
msgstr "%{ kimliğiyle ilişkilendirilmiş bir plan yok s"
@@ -770,7 +778,7 @@ msgstr "Şifre ve onay eşleşmelidir"
msgid "research output not found"
msgstr "araştırma çıktısı bulunamadı"
-#: ../../app/controllers/roles_controller.rb:26
+#: ../../app/controllers/roles_controller.rb:27
msgid ""
"Cannot share plan with %{email} since that email matches\n"
" with the owner of the plan."
@@ -943,27 +951,27 @@ msgstr "Hesabınız başarıyla %{scheme} şemasına bağlandı."
msgid "Unable to link your account to %{scheme}."
msgstr "Hesabınız %{scheme} şemasına bağlanamadı."
-#: ../../app/controllers/users_controller.rb:149
+#: ../../app/controllers/users_controller.rb:150
msgid "Successfully %{action} %{username}'s account."
msgstr "%{username} adlı kullanıcının hesabı başarıyla %{action}."
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "activated"
msgstr "etkinleştirildi"
-#: ../../app/controllers/users_controller.rb:150
+#: ../../app/controllers/users_controller.rb:151
msgid "deactivated"
msgstr "devre dışı bırakıldı"
-#: ../../app/controllers/users_controller.rb:156
+#: ../../app/controllers/users_controller.rb:157
msgid "Unable to %{action} %{username}"
msgstr " %{username} %{action} yapılamıyor"
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "activate"
msgstr "etkinleştir"
-#: ../../app/controllers/users_controller.rb:157
+#: ../../app/controllers/users_controller.rb:158
msgid "deactivate"
msgstr "devre dışı bırak"
@@ -1255,50 +1263,50 @@ msgstr "Son 9 ay"
msgid "Last 12 months"
msgstr "Son 12 ay"
-#: ../../app/mailers/user_mailer.rb:17
+#: ../../app/mailers/user_mailer.rb:18
#: ../../app/views/devise/mailer/invitation_instructions.html.erb:5
#: ../../app/views/devise/mailer/reset_password_instructions.html.erb:5
#: ../../app/views/user_mailer/_email_signature.html.erb:2
msgid "Query or feedback related to %{tool_name}"
msgstr "%{tool_name} ile ilgili sorgu veya geri bildirim"
-#: ../../app/mailers/user_mailer.rb:25
+#: ../../app/mailers/user_mailer.rb:26
msgid "Welcome to %{tool_name}"
msgstr "%{tool_name} aracına hoş geldiniz"
-#: ../../app/mailers/user_mailer.rb:62
+#: ../../app/mailers/user_mailer.rb:63
msgid "A Data Management Plan in %{tool_name} has been shared with you"
msgstr "%{tool_name} içinde bir Veri Yönetim Planı sizinle paylaşıldı"
-#: ../../app/mailers/user_mailer.rb:79
+#: ../../app/mailers/user_mailer.rb:80
msgid "Changed permissions on a Data Management Plan in %{tool_name}"
msgstr "%{tool_name} aracındaki bir Veri Yönetim Planına ilişkin değiştirilen izinler"
-#: ../../app/mailers/user_mailer.rb:94
+#: ../../app/mailers/user_mailer.rb:95
msgid "Permissions removed on a DMP in %{tool_name}"
msgstr "%{tool_name} içindeki bir VYP'de izinler kaldırıldı"
-#: ../../app/mailers/user_mailer.rb:112
+#: ../../app/mailers/user_mailer.rb:113
msgid "%{user_name} has requested feedback on a %{tool_name} plan"
msgstr "%{user_name}, bir %{tool_name} planı hakkında geri bildirim istedi"
-#: ../../app/mailers/user_mailer.rb:135
+#: ../../app/mailers/user_mailer.rb:136
msgid "%{tool_name}: Expert feedback has been provided for %{plan_title}"
msgstr "%{tool_name}: %{plan_title} için uzman geri bildirimi sağlandı"
-#: ../../app/mailers/user_mailer.rb:153
+#: ../../app/mailers/user_mailer.rb:154
msgid "DMP Visibility Changed: %{plan_title}"
msgstr "VYP Görünürlüğü Değiştirildi: %{plan_title}"
-#: ../../app/mailers/user_mailer.rb:182
+#: ../../app/mailers/user_mailer.rb:183
msgid "%{tool_name}: A new comment was added to %{plan_title}"
msgstr "%{tool_name}: %{plan_title} adlı plana yeni bir yorum eklendi"
-#: ../../app/mailers/user_mailer.rb:198
+#: ../../app/mailers/user_mailer.rb:199
msgid "Administrator privileges granted in %{tool_name}"
msgstr "%{tool_name} içinde verilen yönetici ayrıcalıkları"
-#: ../../app/mailers/user_mailer.rb:216
+#: ../../app/mailers/user_mailer.rb:217
msgid "%{tool_name} API changes"
msgstr "%{tool_name} API değişiklikleri"
@@ -1534,15 +1542,15 @@ msgstr ""
msgid "already assigned a value"
msgstr "zaten bir değer atanmış"
-#: ../../app/models/org.rb:46
+#: ../../app/models/org.rb:47
msgid "Feedback email message"
msgstr "Geri bildirim e-posta iletisi"
-#: ../../app/models/org.rb:123
+#: ../../app/models/org.rb:124
msgid "must be one of the following formats: jpeg, jpg, png, gif, bmp"
msgstr "şu biçimlerden biri olmalıdır: jpeg, jpg, png, gif, bmp"
-#: ../../app/models/org.rb:128
+#: ../../app/models/org.rb:129
msgid "can't be larger than 500KB"
msgstr "500KB'den büyük olamaz"
@@ -1666,7 +1674,7 @@ msgstr "Bir bölümünde soru bulunmayan bir şablonu yayınlayamazsınız."
msgid "Conditions in the template refer backwards"
msgstr "Şablondaki koşullar geriye dönük"
-#: ../../app/models/user.rb:380
+#: ../../app/models/user.rb:386
msgid "A Data Management Plan in %{application_name} has been shared with you"
msgstr "%{application_name} içinde bir Veri Yönetim Planı sizinle paylaşıldı"
@@ -2094,7 +2102,7 @@ msgstr ""
#: ../../app/views/paginable/templates/_organisational.html.erb:87
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:29
#: ../../app/views/paginable/templates/_publicly_visible.html.erb:36
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
#: ../../app/views/static_pages/about_us.html.erb:22
#: ../../app/views/static_pages/about_us.html.erb:29
#: ../../app/views/static_pages/termsuse.html.erb:46
@@ -4595,7 +4603,7 @@ msgstr "Yorumlar ve Rehberlik"
msgid "Instructions"
msgstr "Talimatlar"
-#: ../../app/views/plans/_download_form.html.erb:6
+#: ../../app/views/plans/_download_form.html.erb:5
msgid "Format"
msgstr "Biçim"
@@ -4603,71 +4611,71 @@ msgstr "Biçim"
msgid "Download settings"
msgstr "İndirme ayarları"
-#: ../../app/views/plans/_download_form.html.erb:19
-msgid "Select phase to download"
-msgstr "İndirilecek aşamayı seçin"
-
-#: ../../app/views/plans/_download_form.html.erb:26
+#: ../../app/views/plans/_download_form.html.erb:21
msgid "Optional plan components"
msgstr "İsteğe bağlı plan bileşenleri"
-#: ../../app/views/plans/_download_form.html.erb:30
+#: ../../app/views/plans/_download_form.html.erb:25
msgid "project details coversheet"
msgstr "proje detayları kapak sayfası"
-#: ../../app/views/plans/_download_form.html.erb:36
+#: ../../app/views/plans/_download_form.html.erb:31
msgid "question text and section headings"
msgstr "soru metni ve bölüm başlıkları"
-#: ../../app/views/plans/_download_form.html.erb:42
+#: ../../app/views/plans/_download_form.html.erb:37
msgid "unanswered questions"
msgstr "cevaplanmamış sorular"
-#: ../../app/views/plans/_download_form.html.erb:49
+#: ../../app/views/plans/_download_form.html.erb:44
msgid "research outputs"
msgstr "araştırma çıktıları"
-#: ../../app/views/plans/_download_form.html.erb:57
+#: ../../app/views/plans/_download_form.html.erb:52
msgid "supplementary section(s) not requested by funding organisation"
msgstr "Fon sağlayıcı kurum tarafından talep edilmeyen ek bölüm(ler)"
-#: ../../app/views/plans/_download_form.html.erb:65
+#: ../../app/views/plans/_download_form.html.erb:61
+msgid "Select phase to download"
+msgstr "İndirilecek aşamayı seçin"
+
+#: ../../app/views/plans/_download_form.html.erb:70
msgid "PDF formatting"
msgstr "PDF biçimlendirme"
-#: ../../app/views/plans/_download_form.html.erb:68
+#: ../../app/views/plans/_download_form.html.erb:73
msgid "Font"
msgstr "Yazı tipi"
-#: ../../app/views/plans/_download_form.html.erb:71
+#: ../../app/views/plans/_download_form.html.erb:76
msgid "Margin (mm)"
msgstr "Kenar boşluğu (mm)"
-#: ../../app/views/plans/_download_form.html.erb:76
+#: ../../app/views/plans/_download_form.html.erb:81
msgid "Face"
msgstr "Yüz"
-#: ../../app/views/plans/_download_form.html.erb:84
+#: ../../app/views/plans/_download_form.html.erb:89
msgid "Size"
msgstr "Boyut"
-#: ../../app/views/plans/_download_form.html.erb:92
+#: ../../app/views/plans/_download_form.html.erb:96
msgid "Top"
msgstr "Üst"
-#: ../../app/views/plans/_download_form.html.erb:101
+#: ../../app/views/plans/_download_form.html.erb:105
msgid "Bottom"
msgstr "Alt"
-#: ../../app/views/plans/_download_form.html.erb:110
+#: ../../app/views/plans/_download_form.html.erb:114
msgid "Left"
msgstr "Kalan"
-#: ../../app/views/plans/_download_form.html.erb:119
+#: ../../app/views/plans/_download_form.html.erb:123
msgid "Right"
msgstr "Yetki"
-#: ../../app/views/plans/_download_form.html.erb:130
+#: ../../app/views/plans/_download_form.html.erb:133
msgid ""
"Download Plan (new window)%{open_in_new_window_text}"
diff --git a/config/locales/.translation_io b/config/locales/.translation_io
index 41850daef0..934fc62ef3 100644
--- a/config/locales/.translation_io
+++ b/config/locales/.translation_io
@@ -5,4 +5,4 @@
# ignore the conflicts and "sync" again, it will fix this file for you.
---
-timestamp: 1744313316
+timestamp: 1766503989
diff --git a/config/locales/doorkeeper.en.yml b/config/locales/doorkeeper.en.yml
new file mode 100644
index 0000000000..b3c4b2c660
--- /dev/null
+++ b/config/locales/doorkeeper.en.yml
@@ -0,0 +1,154 @@
+en:
+ activerecord:
+ attributes:
+ doorkeeper/application:
+ name: 'Name'
+ redirect_uri: 'Redirect URI'
+ errors:
+ models:
+ doorkeeper/application:
+ attributes:
+ redirect_uri:
+ fragment_present: 'cannot contain a fragment.'
+ invalid_uri: 'must be a valid URI.'
+ unspecified_scheme: 'must specify a scheme.'
+ relative_uri: 'must be an absolute URI.'
+ secured_uri: 'must be an HTTPS/SSL URI.'
+ forbidden_uri: 'is forbidden by the server.'
+ scopes:
+ not_match_configured: "doesn't match configured on the server."
+
+ doorkeeper:
+ applications:
+ confirmations:
+ destroy: 'Are you sure?'
+ buttons:
+ edit: 'Edit'
+ destroy: 'Destroy'
+ submit: 'Submit'
+ cancel: 'Cancel'
+ authorize: 'Authorize'
+ form:
+ error: 'Whoops! Check your form for possible errors'
+ help:
+ confidential: 'Application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential.'
+ redirect_uri: 'Use one line per URI'
+ blank_redirect_uri: "Leave it blank if you configured your provider to use Client Credentials, Resource Owner Password Credentials or any other grant type that doesn't require redirect URI."
+ scopes: 'Separate scopes with spaces. Leave blank to use the default scopes.'
+ edit:
+ title: 'Edit application'
+ index:
+ title: 'Your applications'
+ new: 'New Application'
+ name: 'Name'
+ callback_url: 'Callback URL'
+ confidential: 'Confidential?'
+ actions: 'Actions'
+ confidentiality:
+ 'yes': 'Yes'
+ 'no': 'No'
+ new:
+ title: 'New Application'
+ show:
+ title: 'Application: %{name}'
+ application_id: 'UID'
+ secret: 'Secret'
+ secret_hashed: 'Secret hashed'
+ scopes: 'Scopes'
+ confidential: 'Confidential'
+ callback_urls: 'Callback urls'
+ actions: 'Actions'
+ not_defined: 'Not defined'
+
+ authorizations:
+ buttons:
+ authorize: 'Authorize'
+ deny: 'Deny'
+ error:
+ title: 'An error has occurred'
+ new:
+ title: 'Authorization required'
+ prompt: 'Authorize %{client_name} to use your account?'
+ able_to: 'This application will be able to'
+ show:
+ title: 'Authorization code'
+ form_post:
+ title: 'Submit this form'
+
+ authorized_applications:
+ confirmations:
+ revoke: 'Are you sure?'
+ buttons:
+ revoke: 'Revoke'
+ index:
+ title: 'Your authorized applications'
+ application: 'Application'
+ created_at: 'Created At'
+ date_format: '%Y-%m-%d %H:%M:%S'
+
+ pre_authorization:
+ status: 'Pre-authorization'
+
+ errors:
+ messages:
+ # Common error messages
+ invalid_request:
+ unknown: 'The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.'
+ missing_param: 'Missing required parameter: %{value}.'
+ request_not_authorized: 'Request need to be authorized. Required parameter for authorizing request is missing or invalid.'
+ invalid_redirect_uri: "The requested redirect uri is malformed or doesn't match client redirect URI."
+ unauthorized_client: 'The client is not authorized to perform this request using this method.'
+ access_denied: 'The resource owner or authorization server denied the request.'
+ invalid_scope: 'The requested scope is invalid, unknown, or malformed.'
+ invalid_code_challenge_method:
+ zero: 'The authorization server does not support PKCE as there are no accepted code_challenge_method values.'
+ one: 'The code_challenge_method must be %{challenge_methods}.'
+ other: 'The code_challenge_method must be one of %{challenge_methods}.'
+ server_error: 'The authorization server encountered an unexpected condition which prevented it from fulfilling the request.'
+ temporarily_unavailable: 'The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.'
+
+ # Configuration error messages
+ credential_flow_not_configured: 'Resource Owner Password Credentials flow failed due to Doorkeeper.configure.resource_owner_from_credentials being unconfigured.'
+ resource_owner_authenticator_not_configured: 'Resource Owner find failed due to Doorkeeper.configure.resource_owner_authenticator being unconfigured.'
+ admin_authenticator_not_configured: 'Access to admin panel is forbidden due to Doorkeeper.configure.admin_authenticator being unconfigured.'
+
+ # Access grant errors
+ unsupported_response_type: 'The authorization server does not support this response type.'
+ unsupported_response_mode: 'The authorization server does not support this response mode.'
+
+ # Access token errors
+ invalid_client: 'Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method.'
+ invalid_grant: 'The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.'
+ unsupported_grant_type: 'The authorization grant type is not supported by the authorization server.'
+
+ invalid_token:
+ revoked: "The access token was revoked"
+ expired: "The access token expired"
+ unknown: "The access token is invalid"
+ revoke:
+ unauthorized: "You are not authorized to revoke this token"
+
+ forbidden_token:
+ missing_scope: 'Access to this resource requires scope "%{oauth_scopes}".'
+
+ flash:
+ applications:
+ create:
+ notice: 'Application created.'
+ destroy:
+ notice: 'Application deleted.'
+ update:
+ notice: 'Application updated.'
+ authorized_applications:
+ destroy:
+ notice: 'Application revoked.'
+
+ layouts:
+ admin:
+ title: 'Doorkeeper'
+ nav:
+ oauth2_provider: 'OAuth2 Provider'
+ applications: 'Applications'
+ home: 'Home'
+ application:
+ title: 'OAuth authorization required'
diff --git a/config/locales/translation.de.yml b/config/locales/translation.de.yml
index f0e01bc673..bdf11acbeb 100644
--- a/config/locales/translation.de.yml
+++ b/config/locales/translation.de.yml
@@ -143,6 +143,23 @@ de:
has_one: Datensatz kann nicht gelöscht werden, da ein abhängiger %{record}
existiert.
has_many: Datensatz kann nicht gelöscht werden, da abhängige %{record} existieren.
+ models:
+ doorkeeper/application:
+ attributes:
+ redirect_uri:
+ fragment_present: darf kein Fragment enthalten.
+ invalid_uri: muss ein valider URI (Identifier) sein.
+ unspecified_scheme: muss ein Schema angeben.
+ relative_uri: muss ein absoluter URI (Identifier) sein.
+ secured_uri: muss ein HTTPS/SSL URI (Identifier) sein.
+ forbidden_uri: ist vom server verboten.
+ scopes:
+ not_match_configured: stimmen nicht mit denen am server hinterlegten
+ überein.
+ attributes:
+ doorkeeper/application:
+ name: Name
+ redirect_uri: Redirect URI
datetime:
distance_in_words:
half_a_minute: einer halben Minute
@@ -361,3 +378,146 @@ de:
Sie es erneut.
recaptcha_unreachable: Ups, wir konnten Ihre reCAPTCHA-Antwort nicht validieren.
Bitte versuche es erneut.
+ doorkeeper:
+ applications:
+ confirmations:
+ destroy: Bist du sicher?
+ buttons:
+ edit: Bearbeiten
+ destroy: Löschen
+ submit: Übertragen
+ cancel: Abbrechen
+ authorize: Autorisieren
+ form:
+ error: Whoops! Bitte überprüfe das Formular auf Fehler!
+ help:
+ confidential: Application will be used where the client secret can be kept
+ confidential. Native mobile apps and Single Page Apps are considered non-confidential.
+ redirect_uri: Bitte benutze eine Zeile pro URI
+ blank_redirect_uri: Leave it blank if you configured your provider to use
+ Client Credentials, Resource Owner Password Credentials or any other grant
+ type that doesn't require redirect URI.
+ scopes: Bitte die "Scopes" mit Leerzeichen trennen. Bitte frei lassen für
+ die Verwendung der Default-Werte.
+ edit:
+ title: Applikation bearbeiten
+ index:
+ title: Deine Applikationen
+ new: Neue Applikation
+ name: Name
+ callback_url: Callback URL
+ confidential: Vertraulich?
+ actions: Aktionen
+ confidentiality:
+ 'yes': Ja
+ 'no': Nein
+ new:
+ title: Neue Applikation
+ show:
+ title: 'Applikation: %{name}'
+ application_id: Applikations-ID
+ secret: Secret
+ secret_hashed:
+ scopes: Scopes
+ confidential: Vertraulich
+ callback_urls: Callback URLs
+ actions: Aktionen
+ not_defined:
+ authorizations:
+ buttons:
+ authorize: Autorisieren
+ deny: Verweigern
+ error:
+ title: Ein Fehler ist aufgetreten
+ new:
+ title: Autorisierung erforderlich
+ prompt: Soll %{client_name} für die Benutzung dieses Accounts autorisiert
+ werden?
+ able_to: Diese Anwendung wird folgende Rechte haben
+ show:
+ title: Autorisierungscode
+ form_post:
+ title:
+ authorized_applications:
+ confirmations:
+ revoke: Bist du sicher?
+ buttons:
+ revoke: Ungültig machen
+ index:
+ title: Deine autorisierten Applikationen
+ application: Applikation
+ created_at: erstellt am
+ date_format: "%Y-%m-%d %H:%M:%S"
+ pre_authorization:
+ status: Pre-authorization
+ errors:
+ messages:
+ invalid_request:
+ unknown: Die Anfrage enthält einen nicht-unterstützten Parameter, ein Parameter
+ fehlt oder sie ist anderweitig fehlerhaft.
+ missing_param: 'Missing required parameter: %{value}.'
+ request_not_authorized: Request need to be authorized. Required parameter
+ for authorizing request is missing or invalid.
+ invalid_code_challenge:
+ invalid_redirect_uri: Der Redirect-URI in der Anfrage ist ungültig.
+ unauthorized_client: Der Client ist nicht autorisiert, diese Anfrage mit dieser
+ Methode auszuführen.
+ access_denied: Der Resource Owner oder der Autorisierungs-Server hat die Anfrage
+ verweigert.
+ invalid_scope: Der angeforderte Scope ist inkorrekt, unbekannt oder fehlerhaft.
+ invalid_code_challenge_method:
+ zero:
+ one:
+ other:
+ server_error: Der Autorisierungs-Server hat ein unerwartetes Problem festgestellt
+ und konnte die Anfrage nicht beenden.
+ temporarily_unavailable: Der Autorisierungs-Server ist derzeit auf Grund von
+ temporärer Überlastung oder Wartungsarbeiten am Server nicht in der Lage,
+ die Anfrage zu bearbeiten .
+ credential_flow_not_configured: 'Die Prozedur "Resource Owner Password Credentials"
+ ist fehlgeschlagen: Doorkeeper.configure.resource_owner_from_credentials
+ ist nicht konfiguriert.'
+ resource_owner_authenticator_not_configured: 'Die Prozedur "Resource Owner
+ find" ist fehlgeschlagen: Doorkeeper.configure.resource_owner_authenticator
+ ist nicht konfiguriert.'
+ admin_authenticator_not_configured: Access to admin panel is forbidden due
+ to Doorkeeper.configure.admin_authenticator being unconfigured.
+ unsupported_response_type: Der Autorisierungs-Server unterstützt diesen Antwort-Typ
+ nicht.
+ unsupported_response_mode:
+ invalid_client: 'Client-Autorisierung MKIM ist fehlgeschlagen: Unbekannter
+ Client, keine Autorisierung mitgeliefert oder Autorisierungsmethode nicht
+ unterstützt.'
+ invalid_grant: Die bereitgestellte Autorisierung ist inkorrekt, abgelaufen,
+ widerrufen, ist mit einem anderen Client verknüpft oder der Redirection
+ URI stimmt nicht mit der Autorisierungs-Anfrage überein.
+ unsupported_grant_type: Der Autorisierungs-Typ wird nicht vom Autorisierungs-Server
+ unterstützt.
+ invalid_token:
+ revoked: Der Access Token wurde annuliert
+ expired: Der Access Token ist abgelaufen
+ unknown: Der Access Token ist nicht gültig/korrekt
+ revoke:
+ unauthorized: Sie sind nicht berechtigt, dieses Token zu widerrufen
+ forbidden_token:
+ missing_scope:
+ flash:
+ applications:
+ create:
+ notice: Applikation erstellt.
+ destroy:
+ notice: Applikation gelöscht.
+ update:
+ notice: Applikation geupdated.
+ authorized_applications:
+ destroy:
+ notice: Applikation widerrufen.
+ layouts:
+ admin:
+ title: Doorkeeper
+ nav:
+ oauth2_provider: OAuth2 Provider
+ applications: Applikationen
+ home: Home
+ application:
+ title: OAuth Autorisierung erforderlich
diff --git a/config/locales/translation.en-CA.yml b/config/locales/translation.en-CA.yml
index 9e5ed6e7c8..be1ccaed77 100644
--- a/config/locales/translation.en-CA.yml
+++ b/config/locales/translation.en-CA.yml
@@ -134,6 +134,22 @@ en-CA:
restrict_dependent_destroy:
has_one: Cannot delete record because a dependent %{record} exists
has_many: Cannot delete record because dependent %{record} exist
+ models:
+ doorkeeper/application:
+ attributes:
+ redirect_uri:
+ fragment_present: cannot contain a fragment.
+ invalid_uri: must be a valid URI.
+ unspecified_scheme: must specify a scheme.
+ relative_uri: must be an absolute URI.
+ secured_uri: must be an HTTPS/SSL URI.
+ forbidden_uri: is forbidden by the server.
+ scopes:
+ not_match_configured: doesn't match configured on the server.
+ attributes:
+ doorkeeper/application:
+ name: Name
+ redirect_uri: Redirect URI
datetime:
distance_in_words:
half_a_minute: half a minute
@@ -230,7 +246,8 @@ en-CA:
not_found_in_database: Invalid %{authentication_keys} or password.
timeout: Your session expired. Please sign in again to continue.
unauthenticated: You need to sign in or sign up before continuing.
- unconfirmed: You have to confirm your email address before continuing.
+ unconfirmed: You need to confirm your account before continuing. (Click to request a new confirmation email)
invited:
mailer:
confirmation_instructions:
@@ -340,3 +357,140 @@ en-CA:
previous: "‹ Prev"
next: Next ›
truncate: "…"
+ doorkeeper:
+ applications:
+ confirmations:
+ destroy: Are you sure?
+ buttons:
+ edit: Edit
+ destroy: Destroy
+ submit: Submit
+ cancel: Cancel
+ authorize: Authorize
+ form:
+ error: Whoops! Check your form for possible errors
+ help:
+ confidential: Application will be used where the client secret can be kept
+ confidential. Native mobile apps and Single Page Apps are considered non-confidential.
+ redirect_uri: Use one line per URI
+ blank_redirect_uri: Leave it blank if you configured your provider to use
+ Client Credentials, Resource Owner Password Credentials or any other grant
+ type that doesn't require redirect URI.
+ scopes: Separate scopes with spaces. Leave blank to use the default scopes.
+ edit:
+ title: Edit application
+ index:
+ title: Your applications
+ new: New Application
+ name: Name
+ callback_url: Callback URL
+ confidential: Confidential?
+ actions: Actions
+ confidentiality:
+ 'yes': 'Yes'
+ 'no': 'No'
+ new:
+ title: New Application
+ show:
+ title: 'Application: %{name}'
+ application_id: Application UID
+ secret: Secret
+ secret_hashed:
+ scopes: Scopes
+ confidential: Confidential
+ callback_urls: Callback urls
+ actions: Actions
+ not_defined:
+ authorizations:
+ buttons:
+ authorize: Authorize
+ deny: Deny
+ error:
+ title: An error has occurred
+ new:
+ title: Authorization required
+ prompt: Authorize %{client_name} to use your account?
+ able_to: This application will be able to
+ show:
+ title: Authorization code
+ form_post:
+ title:
+ authorized_applications:
+ confirmations:
+ revoke: Are you sure?
+ buttons:
+ revoke: Revoke
+ index:
+ title: Your authorized applications
+ application: Application
+ created_at: Created At
+ date_format: "%Y-%m-%d %H:%M:%S"
+ pre_authorization:
+ status: Pre-authorization
+ errors:
+ messages:
+ invalid_request:
+ unknown: The request is missing a required parameter, includes an unsupported
+ parameter value, or is otherwise malformed.
+ missing_param: 'Missing required parameter: %{value}.'
+ request_not_authorized: Request need to be authorized. Required parameter
+ for authorizing request is missing or invalid.
+ invalid_code_challenge:
+ invalid_redirect_uri: The requested redirect uri is malformed or doesn't match
+ client redirect URI.
+ unauthorized_client: The client is not authorized to perform this request
+ using this method.
+ access_denied: The resource owner or authorization server denied the request.
+ invalid_scope: The requested scope is invalid, unknown, or malformed.
+ invalid_code_challenge_method:
+ zero:
+ one:
+ other:
+ server_error: The authorization server encountered an unexpected condition
+ which prevented it from fulfilling the request.
+ temporarily_unavailable: The authorization server is currently unable to handle
+ the request due to a temporary overloading or maintenance of the server.
+ credential_flow_not_configured: Resource Owner Password Credentials flow failed
+ due to Doorkeeper.configure.resource_owner_from_credentials being unconfigured.
+ resource_owner_authenticator_not_configured: Resource Owner find failed due
+ to Doorkeeper.configure.resource_owner_authenticator being unconfigured.
+ admin_authenticator_not_configured: Access to admin panel is forbidden due
+ to Doorkeeper.configure.admin_authenticator being unconfigured.
+ unsupported_response_type: The authorization server does not support this
+ response type.
+ unsupported_response_mode:
+ invalid_client: Client authentication failed due to unknown client, no client
+ authentication included, or unsupported authentication method.
+ invalid_grant: The provided authorization grant is invalid, expired, revoked,
+ does not match the redirection URI used in the authorization request, or
+ was issued to another client.
+ unsupported_grant_type: The authorization grant type is not supported by the
+ authorization server.
+ invalid_token:
+ revoked: The access token was revoked
+ expired: The access token expired
+ unknown: The access token is invalid
+ revoke:
+ unauthorized: You are not authorized to revoke this token
+ forbidden_token:
+ missing_scope:
+ flash:
+ applications:
+ create:
+ notice: Application created.
+ destroy:
+ notice: Application deleted.
+ update:
+ notice: Application updated.
+ authorized_applications:
+ destroy:
+ notice: Application revoked.
+ layouts:
+ admin:
+ title: Doorkeeper
+ nav:
+ oauth2_provider: OAuth2 Provider
+ applications: Applications
+ home: Home
+ application:
+ title: OAuth authorization required
diff --git a/config/locales/translation.en-GB.yml b/config/locales/translation.en-GB.yml
index 91014ac51c..c5dfbe313f 100644
--- a/config/locales/translation.en-GB.yml
+++ b/config/locales/translation.en-GB.yml
@@ -134,6 +134,22 @@ en-GB:
restrict_dependent_destroy:
has_one: Cannot delete record because a dependent %{record} exists
has_many: Cannot delete record because dependent %{record} exist
+ models:
+ doorkeeper/application:
+ attributes:
+ redirect_uri:
+ fragment_present: cannot contain a fragment.
+ invalid_uri: must be a valid URI.
+ unspecified_scheme: must specify a scheme.
+ relative_uri: must be an absolute URI.
+ secured_uri: must be an HTTPS/SSL URI.
+ forbidden_uri: is forbidden by the server.
+ scopes:
+ not_match_configured: doesn't match configured on the server.
+ attributes:
+ doorkeeper/application:
+ name: Name
+ redirect_uri: Redirect URI
datetime:
distance_in_words:
half_a_minute: half a minute
@@ -227,7 +243,8 @@ en-GB:
not_found_in_database: Invalid email or password.
timeout: Your session expired, please sign in again to continue.
unauthenticated: You need to sign in or sign up before continuing.
- unconfirmed: You have to confirm your account before continuing.
+ unconfirmed: You need to confirm your account before continuing. (Click to request a new confirmation email)
invited: You have a pending invitation, accept it to finish creating your account.
mailer:
confirmation_instructions:
@@ -341,3 +358,140 @@ en-GB:
errors:
verification_failed:
recaptcha_unreachable:
+ doorkeeper:
+ applications:
+ confirmations:
+ destroy: Are you sure?
+ buttons:
+ edit: Edit
+ destroy: Destroy
+ submit: Submit
+ cancel: Cancel
+ authorize: Authorize
+ form:
+ error: Whoops! Check your form for possible errors
+ help:
+ confidential: Application will be used where the client secret can be kept
+ confidential. Native mobile apps and Single Page Apps are considered non-confidential.
+ redirect_uri: Use one line per URI
+ blank_redirect_uri: Leave it blank if you configured your provider to use
+ Client Credentials, Resource Owner Password Credentials or any other grant
+ type that doesn't require redirect URI.
+ scopes: Separate scopes with spaces. Leave blank to use the default scopes.
+ edit:
+ title: Edit application
+ index:
+ title: Your applications
+ new: New Application
+ name: Name
+ callback_url: Callback URL
+ confidential: Confidential?
+ actions: Actions
+ confidentiality:
+ 'yes': 'Yes'
+ 'no': 'No'
+ new:
+ title: New Application
+ show:
+ title: 'Application: %{name}'
+ application_id: Application UID
+ secret: Secret
+ secret_hashed:
+ scopes: Scopes
+ confidential: Confidential
+ callback_urls: Callback urls
+ actions: Actions
+ not_defined:
+ authorizations:
+ buttons:
+ authorize: Authorize
+ deny: Deny
+ error:
+ title: An error has occurred
+ new:
+ title: Authorization required
+ prompt: Authorize %{client_name} to use your account?
+ able_to: This application will be able to
+ show:
+ title: Authorization code
+ form_post:
+ title:
+ authorized_applications:
+ confirmations:
+ revoke: Are you sure?
+ buttons:
+ revoke: Revoke
+ index:
+ title: Your authorized applications
+ application: Application
+ created_at: Created At
+ date_format: "%Y-%m-%d %H:%M:%S"
+ pre_authorization:
+ status: Pre-authorization
+ errors:
+ messages:
+ invalid_request:
+ unknown: The request is missing a required parameter, includes an unsupported
+ parameter value, or is otherwise malformed.
+ missing_param: 'Missing required parameter: %{value}.'
+ request_not_authorized: Request need to be authorized. Required parameter
+ for authorizing request is missing or invalid.
+ invalid_code_challenge:
+ invalid_redirect_uri: The requested redirect uri is malformed or doesn't match
+ client redirect URI.
+ unauthorized_client: The client is not authorized to perform this request
+ using this method.
+ access_denied: The resource owner or authorization server denied the request.
+ invalid_scope: The requested scope is invalid, unknown, or malformed.
+ invalid_code_challenge_method:
+ zero:
+ one:
+ other:
+ server_error: The authorization server encountered an unexpected condition
+ which prevented it from fulfilling the request.
+ temporarily_unavailable: The authorization server is currently unable to handle
+ the request due to a temporary overloading or maintenance of the server.
+ credential_flow_not_configured: Resource Owner Password Credentials flow failed
+ due to Doorkeeper.configure.resource_owner_from_credentials being unconfigured.
+ resource_owner_authenticator_not_configured: Resource Owner find failed due
+ to Doorkeeper.configure.resource_owner_authenticator being unconfigured.
+ admin_authenticator_not_configured: Access to admin panel is forbidden due
+ to Doorkeeper.configure.admin_authenticator being unconfigured.
+ unsupported_response_type: The authorization server does not support this
+ response type.
+ unsupported_response_mode:
+ invalid_client: Client authentication failed due to unknown client, no client
+ authentication included, or unsupported authentication method.
+ invalid_grant: The provided authorization grant is invalid, expired, revoked,
+ does not match the redirection URI used in the authorization request, or
+ was issued to another client.
+ unsupported_grant_type: The authorization grant type is not supported by the
+ authorization server.
+ invalid_token:
+ revoked: The access token was revoked
+ expired: The access token expired
+ unknown: The access token is invalid
+ revoke:
+ unauthorized: You are not authorized to revoke this token
+ forbidden_token:
+ missing_scope:
+ flash:
+ applications:
+ create:
+ notice: Application created.
+ destroy:
+ notice: Application deleted.
+ update:
+ notice: Application updated.
+ authorized_applications:
+ destroy:
+ notice: Application revoked.
+ layouts:
+ admin:
+ title: Doorkeeper
+ nav:
+ oauth2_provider: OAuth2 Provider
+ applications: Applications
+ home: Home
+ application:
+ title: OAuth authorization required
diff --git a/config/locales/translation.en-US.yml b/config/locales/translation.en-US.yml
index 04f0271b43..7c56f76d0a 100644
--- a/config/locales/translation.en-US.yml
+++ b/config/locales/translation.en-US.yml
@@ -134,6 +134,22 @@ en-US:
restrict_dependent_destroy:
has_one: Cannot delete record because a dependent %{record} exists
has_many: Cannot delete record because dependent %{record} exist
+ models:
+ doorkeeper/application:
+ attributes:
+ redirect_uri:
+ fragment_present: cannot contain a fragment.
+ invalid_uri: must be a valid URI.
+ unspecified_scheme: must specify a scheme.
+ relative_uri: must be an absolute URI.
+ secured_uri: must be an HTTPS/SSL URI.
+ forbidden_uri: is forbidden by the server.
+ scopes:
+ not_match_configured: doesn't match configured on the server.
+ attributes:
+ doorkeeper/application:
+ name: Name
+ redirect_uri: Redirect URI
datetime:
distance_in_words:
half_a_minute: half a minute
@@ -343,3 +359,140 @@ en-US:
errors:
verification_failed:
recaptcha_unreachable:
+ doorkeeper:
+ applications:
+ confirmations:
+ destroy: Are you sure?
+ buttons:
+ edit: Edit
+ destroy: Destroy
+ submit: Submit
+ cancel: Cancel
+ authorize: Authorize
+ form:
+ error: Whoops! Check your form for possible errors
+ help:
+ confidential: Application will be used where the client secret can be kept
+ confidential. Native mobile apps and Single Page Apps are considered non-confidential.
+ redirect_uri: Use one line per URI
+ blank_redirect_uri: Leave it blank if you configured your provider to use
+ Client Credentials, Resource Owner Password Credentials or any other grant
+ type that doesn't require redirect URI.
+ scopes: Separate scopes with spaces. Leave blank to use the default scopes.
+ edit:
+ title: Edit application
+ index:
+ title: Your applications
+ new: New Application
+ name: Name
+ callback_url: Callback URL
+ confidential: Confidential?
+ actions: Actions
+ confidentiality:
+ 'yes': 'Yes'
+ 'no': 'No'
+ new:
+ title: New Application
+ show:
+ title: 'Application: %{name}'
+ application_id: Application UID
+ secret: Secret
+ secret_hashed:
+ scopes: Scopes
+ confidential: Confidential
+ callback_urls: Callback urls
+ actions: Actions
+ not_defined:
+ authorizations:
+ buttons:
+ authorize: Authorize
+ deny: Deny
+ error:
+ title: An error has occurred
+ new:
+ title: Authorization required
+ prompt: Authorize %{client_name} to use your account?
+ able_to: This application will be able to
+ show:
+ title: Authorization code
+ form_post:
+ title:
+ authorized_applications:
+ confirmations:
+ revoke: Are you sure?
+ buttons:
+ revoke: Revoke
+ index:
+ title: Your authorized applications
+ application: Application
+ created_at: Created At
+ date_format: "%Y-%m-%d %H:%M:%S"
+ pre_authorization:
+ status: Pre-authorization
+ errors:
+ messages:
+ invalid_request:
+ unknown: The request is missing a required parameter, includes an unsupported
+ parameter value, or is otherwise malformed.
+ missing_param: 'Missing required parameter: %{value}.'
+ request_not_authorized: Request need to be authorized. Required parameter
+ for authorizing request is missing or invalid.
+ invalid_code_challenge:
+ invalid_redirect_uri: The requested redirect uri is malformed or doesn't match
+ client redirect URI.
+ unauthorized_client: The client is not authorized to perform this request
+ using this method.
+ access_denied: The resource owner or authorization server denied the request.
+ invalid_scope: The requested scope is invalid, unknown, or malformed.
+ invalid_code_challenge_method:
+ zero:
+ one:
+ other:
+ server_error: The authorization server encountered an unexpected condition
+ which prevented it from fulfilling the request.
+ temporarily_unavailable: The authorization server is currently unable to handle
+ the request due to a temporary overloading or maintenance of the server.
+ credential_flow_not_configured: Resource Owner Password Credentials flow failed
+ due to Doorkeeper.configure.resource_owner_from_credentials being unconfigured.
+ resource_owner_authenticator_not_configured: Resource Owner find failed due
+ to Doorkeeper.configure.resource_owner_authenticator being unconfigured.
+ admin_authenticator_not_configured: Access to admin panel is forbidden due
+ to Doorkeeper.configure.admin_authenticator being unconfigured.
+ unsupported_response_type: The authorization server does not support this
+ response type.
+ unsupported_response_mode:
+ invalid_client: Client authentication failed due to unknown client, no client
+ authentication included, or unsupported authentication method.
+ invalid_grant: The provided authorization grant is invalid, expired, revoked,
+ does not match the redirection URI used in the authorization request, or
+ was issued to another client.
+ unsupported_grant_type: The authorization grant type is not supported by the
+ authorization server.
+ invalid_token:
+ revoked: The access token was revoked
+ expired: The access token expired
+ unknown: The access token is invalid
+ revoke:
+ unauthorized: You are not authorized to revoke this token
+ forbidden_token:
+ missing_scope:
+ flash:
+ applications:
+ create:
+ notice: Application created.
+ destroy:
+ notice: Application deleted.
+ update:
+ notice: Application updated.
+ authorized_applications:
+ destroy:
+ notice: Application revoked.
+ layouts:
+ admin:
+ title: Doorkeeper
+ nav:
+ oauth2_provider: OAuth2 Provider
+ applications: Applications
+ home: Home
+ application:
+ title: OAuth authorization required
diff --git a/config/locales/translation.es.yml b/config/locales/translation.es.yml
index 7491ded07f..ba5ef434ce 100644
--- a/config/locales/translation.es.yml
+++ b/config/locales/translation.es.yml
@@ -141,6 +141,22 @@ es:
restrict_dependent_destroy:
has_one: No se puede eliminar el registro porque existe un %{record} dependiente
has_many: No se puede eliminar el registro porque existen %{record} dependientes
+ models:
+ doorkeeper/application:
+ attributes:
+ redirect_uri:
+ fragment_present: no puede contener un fragmento.
+ invalid_uri: debe ser una URI válida.
+ unspecified_scheme: debe especificar un esquema.
+ relative_uri: debe ser una URI absoluta.
+ secured_uri: debe ser una URI HTTPS/SSL.
+ forbidden_uri: está prohibido por el servidor.
+ scopes:
+ not_match_configured: doesn't match configured on the server.
+ attributes:
+ doorkeeper/application:
+ name: Nombre
+ redirect_uri: URI de redirección
datetime:
distance_in_words:
half_a_minute: medio minuto
@@ -353,3 +369,144 @@ es:
verification_failed: La verificación reCAPTCHA falló, por favor intente nuevamente.
recaptcha_unreachable: Vaya, no hemos podido validar su respuesta reCAPTCHA.
Inténtalo de nuevo.
+ doorkeeper:
+ applications:
+ confirmations:
+ destroy: "¿Estás seguro?"
+ buttons:
+ edit: Editar
+ destroy: Eliminar
+ submit: Enviar
+ cancel: Cancelar
+ authorize: Autorizar
+ form:
+ error: Ups! Verifica tu formulario por posibles errores
+ help:
+ confidential: Application will be used where the client secret can be kept
+ confidential. Native mobile apps and Single Page Apps are considered non-confidential.
+ redirect_uri: Usa una linea por URI
+ blank_redirect_uri: Leave it blank if you configured your provider to use
+ Client Credentials, Resource Owner Password Credentials or any other grant
+ type that doesn't require redirect URI.
+ scopes: Separa los ámbitos con espacios. Deja en blanco para usar los ámbitos
+ predeterminados.
+ edit:
+ title: Editar aplicación
+ index:
+ title: Tus aplicaciones
+ new: Nueva aplicación
+ name: Nombre
+ callback_url: Callback URL
+ confidential: Confidential?
+ actions: Actions
+ confidentiality:
+ 'yes': Sí
+ 'no': 'No'
+ new:
+ title: Nueva aplicación
+ show:
+ title: 'Aplicación: %{name}'
+ application_id: Identificador de aplicación
+ secret: Secret
+ secret_hashed:
+ scopes: Ámbitos
+ confidential: Confidential
+ callback_urls: Callback urls
+ actions: Acciones
+ not_defined:
+ authorizations:
+ buttons:
+ authorize: Autorizar
+ deny: Denegar
+ error:
+ title: Ha ocurrido un error
+ new:
+ title: Autorización requerida
+ prompt: "¿Autorizas a %{client_name} para usar tu cuenta?"
+ able_to: Está aplicación tendrá permisos para
+ show:
+ title: Código de autorización
+ form_post:
+ title:
+ authorized_applications:
+ confirmations:
+ revoke: "¿Estás seguro?"
+ buttons:
+ revoke: Revocar
+ index:
+ title: Tus aplicaciones autorizadas
+ application: Aplicación
+ created_at: Creada el
+ date_format: "%d/%m/%Y %H:%M:%S"
+ pre_authorization:
+ status: Pre-authorization
+ errors:
+ messages:
+ invalid_request:
+ unknown: La petición no tiene un parámetro obligatorio, incluye un valor
+ de parámetro incompatible, o tiene un formato incorrecto.
+ missing_param: 'Missing required parameter: %{value}.'
+ request_not_authorized: Request need to be authorized. Required parameter
+ for authorizing request is missing or invalid.
+ invalid_code_challenge:
+ invalid_redirect_uri: La uri de redirección no es valida.
+ unauthorized_client: El cliente no tiene autorización para realizar esta petición
+ utilizando este método.
+ access_denied: El propietario del recurso o el servidor de autorización han
+ denegado la petición.
+ invalid_scope: El scope solicitado no es válido, es desconocido, o tiene un
+ formato incorrecto.
+ invalid_code_challenge_method:
+ zero:
+ one:
+ other:
+ server_error: El servidor de autorización ha encontrado una condición inesperada
+ que le ha impedido completar la petición.
+ temporarily_unavailable: El servidor de autorización no ha podido manejar
+ la petición por una sobrecarga temporal o por mantenimiento del servidor.
+ credential_flow_not_configured: El flujo de credenciales del propietario del
+ recurso ha fallado porque Doorkeeper.configure.resource_owner_from_credentials
+ no está configurado.
+ resource_owner_authenticator_not_configured: La búsqueda del propietario del
+ recurso ha fallado porque Doorkeeper.configure.resource_owner_authenticator
+ no está configurado.
+ admin_authenticator_not_configured: Access to admin panel is forbidden due
+ to Doorkeeper.configure.admin_authenticator being unconfigured.
+ unsupported_response_type: El servidor de autorización no soporta este tipo
+ de respuesta.
+ unsupported_response_mode:
+ invalid_client: La autenticación del cliente ha fallado por cliente desconocido,
+ cliente no autenticado, o método de autenticación incompatible.
+ invalid_grant: La autorización proporcionada no es válida, ha expirado, se
+ ha revocado, no coincide con la URI de redirección utilizada en la petición
+ de autorización, o ha sido solicitada por otro cliente.
+ unsupported_grant_type: El tipo de autorización no está soportada por el servidor
+ de autorización.
+ invalid_token:
+ revoked: El token de acceso ha sido revocado
+ expired: El token de acceso ha expirado
+ unknown: El token de acceso es inválido
+ revoke:
+ unauthorized: No tiene autorización para revocar este token
+ forbidden_token:
+ missing_scope:
+ flash:
+ applications:
+ create:
+ notice: Aplicación creada.
+ destroy:
+ notice: Aplicación eliminada.
+ update:
+ notice: Aplicación actualizada.
+ authorized_applications:
+ destroy:
+ notice: Aplicación revocada.
+ layouts:
+ admin:
+ title: Doorkeeper
+ nav:
+ oauth2_provider: Proveedor OAuth2
+ applications: Aplicaciones
+ home: Home
+ application:
+ title: Autorización OAuth requerida
diff --git a/config/locales/translation.fi.yml b/config/locales/translation.fi.yml
index 7b6eda4977..287ae72e94 100644
--- a/config/locales/translation.fi.yml
+++ b/config/locales/translation.fi.yml
@@ -138,6 +138,22 @@ fi:
restrict_dependent_destroy:
has_one: Ei voida poistaa mallia koska tästä riippuvainen %{record} löytyy
has_many: Ei voida poistaa mallia koska tästä riippuvaisia %{record} löytyy
+ models:
+ doorkeeper/application:
+ attributes:
+ redirect_uri:
+ fragment_present: ei voi sisältää URI fragmenttia.
+ invalid_uri: täytyy olla validi URI.
+ unspecified_scheme: täytyy määrittää järjestelmä.
+ relative_uri: täytyy olla absoluuttinen URI.
+ secured_uri: täytyy olla HTTPS/SSL URI.
+ forbidden_uri: on kielletty palvelimella.
+ scopes:
+ not_match_configured: doesn't match configured on the server.
+ attributes:
+ doorkeeper/application:
+ name: Nimi
+ redirect_uri: Uudelleenohjauksen URI
datetime:
distance_in_words:
half_a_minute: puoli minuuttia
@@ -346,3 +362,143 @@ fi:
verification_failed: reCAPTCHA-vahvistus epäonnistui, yritä uudelleen.
recaptcha_unreachable: Hups, emme vahvistaneet reCAPTCHA-vastaustasi. Yritä
uudelleen.
+ doorkeeper:
+ applications:
+ confirmations:
+ destroy: Oletko varma?
+ buttons:
+ edit: Muokkaa
+ destroy: Poista
+ submit: Lähetä
+ cancel: Peruuta
+ authorize: Valtuuta
+ form:
+ error: Hups! Tarkasta lomakkeesi mahdollisten virheiden varalta.
+ help:
+ confidential: Application will be used where the client secret can be kept
+ confidential. Native mobile apps and Single Page Apps are considered non-confidential.
+ redirect_uri: Yksi URI riviä kohden
+ blank_redirect_uri: Leave it blank if you configured your provider to use
+ Client Credentials, Resource Owner Password Credentials or any other grant
+ type that doesn't require redirect URI.
+ scopes: Erottele näkyvyysalueet välilyönnein. Jätä tyhjäksi, mikäli haluat
+ käyttää oletusnäkyvyysalueita.
+ edit:
+ title: Muokkaa sovellusta
+ index:
+ title: Omat sovellukset
+ new: Uusi sovellus
+ name: Nimi
+ callback_url: Callback URL
+ confidential: Confidential?
+ actions: Actions
+ confidentiality:
+ 'yes': Joo
+ 'no': Ei
+ new:
+ title: Uusi sovellus
+ show:
+ title: 'Sovellus: %{name}'
+ application_id: Sovelluksen UID
+ secret: Salainen avain
+ secret_hashed: Salainen tiivistetty
+ scopes: Näkyvyysalueet
+ confidential: Confidential
+ callback_urls: Callback URL:t
+ actions: Toiminnot
+ not_defined: Ei määritelty
+ authorizations:
+ buttons:
+ authorize: Valtuuta
+ deny: Kiellä
+ error:
+ title: Virhe
+ new:
+ title: Valtuutus vaadittu
+ prompt: Valtuuta %{client_name} käyttämään tiliäsi?
+ able_to: Tämä sovellus pystyy
+ show:
+ title: Valtuutuskoodi
+ form_post:
+ title: Lähetä tämä lomake
+ authorized_applications:
+ confirmations:
+ revoke: Oletko varma?
+ buttons:
+ revoke: Evää
+ index:
+ title: Valtuuttamasi sovellukset
+ application: Sovellukset
+ created_at: Valtuutettu
+ date_format: "%d. %m. %Y klo %H:%M:%S"
+ pre_authorization:
+ status: Pre-authorization
+ errors:
+ messages:
+ invalid_request:
+ unknown: Pyynnöstä puuttuu vaadittu parametri, se sisältää virheellisen
+ parametrin arvon tai on muutoin väärin muodostettu.
+ missing_param: 'Missing required parameter: %{value}.'
+ request_not_authorized: Request need to be authorized. Required parameter
+ for authorizing request is missing or invalid.
+ invalid_code_challenge:
+ invalid_redirect_uri: Uudelleenohjauksen URI ei ole validi.
+ unauthorized_client: Asiakasohjelmaa ei ole valtuutettu suorittamaan haluttua
+ pyyntöä käyttäen tätä metodia.
+ access_denied: Resurssin omistaja tai valtuutuspalvelin kieltäytyi suorittamasta
+ pyyntöä.
+ invalid_scope: Pyynnön näkyvyysalue on virheellinen, tuntematon tai väärin
+ muodostettu.
+ invalid_code_challenge_method:
+ zero: Valtuutuspalvelin ei tue PKCE:tä, koska hyväksyttyjä code_challenge_method-arvoja
+ ei ole.
+ one: Koodihaastemetodin on oltava muotoa %{challenge_methods}.
+ other: 'Koodihaastemetodin on oltava jokin seuraavista: %{challenge_methods}.'
+ server_error: Valtuutuspalvelin kohtasi odottamattoman tilan, jonka seurauksena
+ se ei pystynyt suorittamaan pyyntöä.
+ temporarily_unavailable: Valtuutuspalvelin ei tällä hetkellä pysty suorittamaan
+ pyyntöä väliaikaisen ylikuormituksen tai palvelinhuollon takia.
+ credential_flow_not_configured: '"Resource Owner Password Credentials flow"
+ - proseduuri epäonnistui, koska Doorkeeper.configure.resource_owner_from_credentials
+ -asetusta ei ole konfiguroitu.'
+ resource_owner_authenticator_not_configured: '"Resource Owner find" - proseduuri
+ epäonnistui, koska Doorkeeper.configure.resource_owner_authenticator -asetusta
+ ei ole konfiguroitu.'
+ admin_authenticator_not_configured: Access to admin panel is forbidden due
+ to Doorkeeper.configure.admin_authenticator being unconfigured.
+ unsupported_response_type: Valtuutuspalvelin ei tue tämän tyyppisiä vastauksia.
+ unsupported_response_mode: Valtuutuspalvelin ei tue tätä vastaustilaa.
+ invalid_client: Asiakasohjelman valtuutus epäonnistui tuntemattoman asiakasohjelman,
+ virheellisen valtuutuksen tai tukemattoman valtuutusmetodin takia.
+ invalid_grant: Toimitettu valtuutus on virheellinen, vanhentunut, evätty,
+ se ei vastaa valtuutuspyynnön uudelleenohjauksen URI:a tai sen on myöntänyt
+ toinen asiakasohjelma.
+ unsupported_grant_type: Valtuutuspalvelin ei tue tämän tyyppisiä valtuutuksia.
+ invalid_token:
+ revoked: Pääsyoikeus evätty
+ expired: Pääsyoikeus vanhentunut
+ unknown: Pääsyoikeus virheellinen
+ revoke:
+ unauthorized: You are not authorized to revoke this token
+ forbidden_token:
+ missing_scope: Tämän resurssin käyttö edellyttää laajuutta "%{oauth_scopes}".
+ flash:
+ applications:
+ create:
+ notice: Sovellus luotu.
+ destroy:
+ notice: Sovellus poistettu.
+ update:
+ notice: Sovellus päivitetty.
+ authorized_applications:
+ destroy:
+ notice: Sovellus evätty.
+ layouts:
+ admin:
+ title: Doorkeeper
+ nav:
+ oauth2_provider: OAuth2 tarjoaja
+ applications: Sovellukset
+ home: Etusivu
+ application:
+ title: OAuth valtuutus vaadittu.
diff --git a/config/locales/translation.fr-CA.yml b/config/locales/translation.fr-CA.yml
index 8f23004765..10db3d80b6 100644
--- a/config/locales/translation.fr-CA.yml
+++ b/config/locales/translation.fr-CA.yml
@@ -144,6 +144,22 @@ fr-CA:
la) %{record} dépendant(e)
has_many: Vous ne pouvez pas supprimer l’enregistrement en raison du (de
la) %{record} dépendant(e)
+ models:
+ doorkeeper/application:
+ attributes:
+ redirect_uri:
+ fragment_present: ne peut contenir un fragment.
+ invalid_uri: doit être une URL valide.
+ unspecified_scheme: doit spécifier un schéma.
+ relative_uri: doit être une URL absolue.
+ secured_uri: doit être une URL HTTP/SSL.
+ forbidden_uri: est interdit par le serveur.
+ scopes:
+ not_match_configured: doesn't match configured on the server.
+ attributes:
+ doorkeeper/application:
+ name: Nom
+ redirect_uri: L'URL de redirection
datetime:
distance_in_words:
half_a_minute: une demi-minute
@@ -242,7 +258,8 @@ fr-CA:
not_found_in_database: "%{authentication_keys} ou mot de passe incorrect."
timeout: Votre session est expirée. Veuillez vous reconnecter pour continuer.
unauthenticated: Vous devez vous connecter ou vous inscrire pour continuer.
- unconfirmed: Vous devez confirmer votre adresse courriel pour continuer.
+ unconfirmed: Vous devez confirmer votre compte avant de continuer. (cliquez pour demander un nouveau courriel de confirmation)
invited: Vous avez une invitation en attente. Acceptez-la pour terminer la création
de votre compte.
mailer:
@@ -363,3 +380,148 @@ fr-CA:
previous: "‹ précédent(e)"
next: "› suivant(e)"
truncate: "…"
+ doorkeeper:
+ applications:
+ confirmations:
+ destroy: Êtes-vous certain?
+ buttons:
+ edit: Modifier
+ destroy: Supprimer
+ submit: Envoyer
+ cancel: Annuler
+ authorize: Autoriser
+ form:
+ error: Oups! Vérifier votre formulaire pour des erreurs possibles
+ help:
+ confidential: |
+ L'application sera utilisée quand la confidentialité du secret pourra
+ être maintenue. Les application mobile native, et les Applications
+ mono-page ne sont pas considérées comme sûr.
+ redirect_uri: Utiliser une ligne par URL
+ blank_redirect_uri: Leave it blank if you configured your provider to use
+ Client Credentials, Resource Owner Password Credentials or any other grant
+ type that doesn't require redirect URI.
+ scopes: Utilisez un espace entre chaque portée. Laissez vide pour utiliser
+ la portée par defaut
+ edit:
+ title: Modifier l'application
+ index:
+ title: Vos applications
+ new: Nouvelle application
+ name: Nom
+ callback_url: URL de retour d'appel
+ confidential: Confidential?
+ actions: Actions
+ confidentiality:
+ 'yes': Oui
+ 'no': Non
+ new:
+ title: Nouvelle application
+ show:
+ title: 'Application : %{name}'
+ application_id: ID de l'application
+ secret: Secret
+ secret_hashed:
+ scopes: Portées
+ confidential: Confidential
+ callback_urls: URL du retour d'appel
+ actions: Actions
+ not_defined:
+ authorizations:
+ buttons:
+ authorize: Autoriser
+ deny: Refuser
+ error:
+ title: Une erreur est survenue
+ new:
+ title: Autorisation requise
+ prompt: Autorisez %{client_name} à utiliser votre compte?
+ able_to: Cette application pourra
+ show:
+ title: Code d'autorisation
+ form_post:
+ title:
+ authorized_applications:
+ confirmations:
+ revoke: Êtes-vous certain?
+ buttons:
+ revoke: Annuler
+ index:
+ title: Vos applications autorisées
+ application: Application
+ created_at: Créé le
+ date_format: "%Y-%m-%d %H:%M:%S"
+ pre_authorization:
+ status: Pre-authorization
+ errors:
+ messages:
+ invalid_request:
+ unknown: La demande manque un paramètre requis, inclut une valeur de paramètre
+ non prise en charge, ou est autrement mal formée.
+ missing_param: 'Missing required parameter: %{value}.'
+ request_not_authorized: Request need to be authorized. Required parameter
+ for authorizing request is missing or invalid.
+ invalid_code_challenge:
+ invalid_redirect_uri: L'URL de redirection n'est pas valide.
+ unauthorized_client: Le client n'est pas autorisé à effectuer cette demande
+ à l'aide de cette méthode.
+ access_denied: Le propriétaire de la ressource ou le serveur d'autorisation
+ a refusé la demande.
+ invalid_scope: Le scope demandé n'est pas valide, est inconnu, ou est mal
+ formé.
+ invalid_code_challenge_method:
+ zero:
+ one:
+ other:
+ server_error: Le serveur d'autorisation a rencontré une condition inattendue
+ qui l'a empêché de remplir la demande.
+ temporarily_unavailable: Le serveur d'autorisation est actuellement incapable
+ de traiter la demande à cause d'une surcharge ou d'un entretien temporaire
+ du serveur.
+ credential_flow_not_configured: Le flux des identifiants du mot de passe du
+ propriétaire de la ressource a échoué en raison de Doorkeeper.configure.resource_owner_from_credentials
+ n'est pas configuré.
+ resource_owner_authenticator_not_configured: La recherche du propriétaire
+ de la ressource a échoué en raison de Doorkeeper.configure.resource_owner_authenticator
+ n'est pas configuré.
+ admin_authenticator_not_configured: Access to admin panel is forbidden due
+ to Doorkeeper.configure.admin_authenticator being unconfigured.
+ unsupported_response_type: Le serveur d'autorisation ne prend pas en charge
+ ce type de réponse.
+ unsupported_response_mode:
+ invalid_client: L'authentification du client a échoué à cause d'un client
+ inconnu, d'aucune authentification de client incluse, ou d'une méthode d'authentification
+ non prise en charge.
+ invalid_grant: Le consentement d'autorisation accordé n'est pas valide, a
+ expiré, est annulé, ne concorde pas avec l'URL de redirection utilisée dans
+ la demande d'autorisation, ou a été émis à un autre client.
+ unsupported_grant_type: Le type de consentement d'autorisation n'est pas pris
+ en charge par le serveur d'autorisation.
+ invalid_token:
+ revoked: Le jeton d'accès a été annulé
+ expired: Le jeton d'accès a expiré
+ unknown: Le jeton d'accès n'est pas valide
+ revoke:
+ unauthorized: Vous n'êtes pas autorisé à révoquer ce jeton
+ forbidden_token:
+ missing_scope:
+ flash:
+ applications:
+ create:
+ notice: Application créée.
+ destroy:
+ notice: Application supprimée.
+ update:
+ notice: Application mise à jour.
+ authorized_applications:
+ destroy:
+ notice: Application annulée.
+ layouts:
+ admin:
+ title: Doorkeeper
+ nav:
+ oauth2_provider: Fournisseur OAuth2
+ applications: Applications
+ home: Home
+ application:
+ title: Autorisation OAuth requise
diff --git a/config/locales/translation.fr-FR.yml b/config/locales/translation.fr-FR.yml
index ea80971e67..d541b9a742 100644
--- a/config/locales/translation.fr-FR.yml
+++ b/config/locales/translation.fr-FR.yml
@@ -144,6 +144,22 @@ fr-FR:
dépendant(e) existe
has_many: Vous ne pouvez pas supprimer l'enregistrement parce que les %{record}
dépendants existent
+ models:
+ doorkeeper/application:
+ attributes:
+ redirect_uri:
+ fragment_present: ne peut contenir un fragment.
+ invalid_uri: doit être une URL valide.
+ unspecified_scheme: doit spécifier un schéma.
+ relative_uri: doit être une URL absolue.
+ secured_uri: doit être une URL HTTP/SSL.
+ forbidden_uri: est interdit par le serveur.
+ scopes:
+ not_match_configured: doesn't match configured on the server.
+ attributes:
+ doorkeeper/application:
+ name: Nom
+ redirect_uri: L'URL de redirection
datetime:
distance_in_words:
half_a_minute: une demi-minute
@@ -360,3 +376,148 @@ fr-FR:
verification_failed: La vérification reCAPTCHA a échoué, veuillez réessayer.
recaptcha_unreachable: Oups, nous n'avons pas réussi à valider votre réponse
reCAPTCHA. Veuillez réessayer.
+ doorkeeper:
+ applications:
+ confirmations:
+ destroy: Êtes-vous certain?
+ buttons:
+ edit: Modifier
+ destroy: Supprimer
+ submit: Envoyer
+ cancel: Annuler
+ authorize: Autoriser
+ form:
+ error: Oups! Vérifier votre formulaire pour des erreurs possibles
+ help:
+ confidential: |
+ L'application sera utilisée quand la confidentialité du secret pourra
+ être maintenue. Les application mobile native, et les Applications
+ mono-page ne sont pas considérées comme sûr.
+ redirect_uri: Utiliser une ligne par URL
+ blank_redirect_uri: Leave it blank if you configured your provider to use
+ Client Credentials, Resource Owner Password Credentials or any other grant
+ type that doesn't require redirect URI.
+ scopes: Utilisez un espace entre chaque portée. Laissez vide pour utiliser
+ la portée par defaut
+ edit:
+ title: Modifier l'application
+ index:
+ title: Vos applications
+ new: Nouvelle application
+ name: Nom
+ callback_url: URL de retour d'appel
+ confidential: Confidential?
+ actions: Actions
+ confidentiality:
+ 'yes': Oui
+ 'no': Non
+ new:
+ title: Nouvelle application
+ show:
+ title: 'Application : %{name}'
+ application_id: ID de l'application
+ secret: Secret
+ secret_hashed:
+ scopes: Portées
+ confidential: Confidential
+ callback_urls: URL du retour d'appel
+ actions: Actions
+ not_defined:
+ authorizations:
+ buttons:
+ authorize: Autoriser
+ deny: Refuser
+ error:
+ title: Une erreur est survenue
+ new:
+ title: Autorisation requise
+ prompt: Autorisez %{client_name} à utiliser votre compte?
+ able_to: Cette application pourra
+ show:
+ title: Code d'autorisation
+ form_post:
+ title:
+ authorized_applications:
+ confirmations:
+ revoke: Êtes-vous certain?
+ buttons:
+ revoke: Annuler
+ index:
+ title: Vos applications autorisées
+ application: Application
+ created_at: Créé le
+ date_format: "%Y-%m-%d %H:%M:%S"
+ pre_authorization:
+ status: Pre-authorization
+ errors:
+ messages:
+ invalid_request:
+ unknown: La demande manque un paramètre requis, inclut une valeur de paramètre
+ non prise en charge, ou est autrement mal formée.
+ missing_param: 'Missing required parameter: %{value}.'
+ request_not_authorized: Request need to be authorized. Required parameter
+ for authorizing request is missing or invalid.
+ invalid_code_challenge:
+ invalid_redirect_uri: L'URL de redirection n'est pas valide.
+ unauthorized_client: Le client n'est pas autorisé à effectuer cette demande
+ à l'aide de cette méthode.
+ access_denied: Le propriétaire de la ressource ou le serveur d'autorisation
+ a refusé la demande.
+ invalid_scope: Le scope demandé n'est pas valide, est inconnu, ou est mal
+ formé.
+ invalid_code_challenge_method:
+ zero:
+ one:
+ other:
+ server_error: Le serveur d'autorisation a rencontré une condition inattendue
+ qui l'a empêché de remplir la demande.
+ temporarily_unavailable: Le serveur d'autorisation est actuellement incapable
+ de traiter la demande à cause d'une surcharge ou d'un entretien temporaire
+ du serveur.
+ credential_flow_not_configured: Le flux des identifiants du mot de passe du
+ propriétaire de la ressource a échoué en raison de Doorkeeper.configure.resource_owner_from_credentials
+ n'est pas configuré.
+ resource_owner_authenticator_not_configured: La recherche du propriétaire
+ de la ressource a échoué en raison de Doorkeeper.configure.resource_owner_authenticator
+ n'est pas configuré.
+ admin_authenticator_not_configured: Access to admin panel is forbidden due
+ to Doorkeeper.configure.admin_authenticator being unconfigured.
+ unsupported_response_type: Le serveur d'autorisation ne prend pas en charge
+ ce type de réponse.
+ unsupported_response_mode:
+ invalid_client: L'authentification du client a échoué à cause d'un client
+ inconnu, d'aucune authentification de client incluse, ou d'une méthode d'authentification
+ non prise en charge.
+ invalid_grant: Le consentement d'autorisation accordé n'est pas valide, a
+ expiré, est annulé, ne concorde pas avec l'URL de redirection utilisée dans
+ la demande d'autorisation, ou a été émis à un autre client.
+ unsupported_grant_type: Le type de consentement d'autorisation n'est pas pris
+ en charge par le serveur d'autorisation.
+ invalid_token:
+ revoked: Le jeton d'accès a été annulé
+ expired: Le jeton d'accès a expiré
+ unknown: Le jeton d'accès n'est pas valide
+ revoke:
+ unauthorized: Vous n'êtes pas autorisé à révoquer ce jeton
+ forbidden_token:
+ missing_scope:
+ flash:
+ applications:
+ create:
+ notice: Application créée.
+ destroy:
+ notice: Application supprimée.
+ update:
+ notice: Application mise à jour.
+ authorized_applications:
+ destroy:
+ notice: Application annulée.
+ layouts:
+ admin:
+ title: Doorkeeper
+ nav:
+ oauth2_provider: Fournisseur OAuth2
+ applications: Applications
+ home: Home
+ application:
+ title: Autorisation OAuth requise
diff --git a/config/locales/translation.pt-BR.yml b/config/locales/translation.pt-BR.yml
index 9f39d22fb1..dbe1229130 100644
--- a/config/locales/translation.pt-BR.yml
+++ b/config/locales/translation.pt-BR.yml
@@ -143,6 +143,22 @@ pt-BR:
restrict_dependent_destroy:
has_one: Não é possível excluir o registro pois existe um %{record} dependente
has_many: Não é possível excluir o registro pois existem %{record} dependentes
+ models:
+ doorkeeper/application:
+ attributes:
+ redirect_uri:
+ fragment_present: Não pode conter um fragmento.
+ invalid_uri: deve ser uma URI válida.
+ unspecified_scheme: must specify a scheme.
+ relative_uri: dever ser uma URI absoluta.
+ secured_uri: deve ser uma URI HTTPS/SSL.
+ forbidden_uri: is forbidden by the server.
+ scopes:
+ not_match_configured: doesn't match configured on the server.
+ attributes:
+ doorkeeper/application:
+ name: Nome
+ redirect_uri: URI de redirecionamento
datetime:
distance_in_words:
half_a_minute: meio minuto
@@ -357,3 +373,143 @@ pt-BR:
verification_failed: A verificação do reCAPTCHA falhou. Tente novamente.
recaptcha_unreachable: Ops, não foi possível validar sua resposta do reCAPTCHA.
Por favor, tente novamente.
+ doorkeeper:
+ applications:
+ confirmations:
+ destroy: Você tem certeza?
+ buttons:
+ edit: Editar
+ destroy: Deletar
+ submit: Submeter
+ cancel: Cancelar
+ authorize: Autorizar
+ form:
+ error: Whoops! Veja o form para possíveis erros
+ help:
+ confidential: Application will be used where the client secret can be kept
+ confidential. Native mobile apps and Single Page Apps are considered non-confidential.
+ redirect_uri: Use uma linha por URI
+ blank_redirect_uri: Leave it blank if you configured your provider to use
+ Client Credentials, Resource Owner Password Credentials or any other grant
+ type that doesn't require redirect URI.
+ scopes:
+ edit:
+ title: Editar aplicação
+ index:
+ title: Suas aplicações
+ new: Nova Aplicação
+ name: Nome
+ callback_url: URL de Callback
+ confidential: Confidential?
+ actions: Actions
+ confidentiality:
+ 'yes': Sim
+ 'no': Não
+ new:
+ title: Nova Aplicação
+ show:
+ title: 'Aplicação: %{name}'
+ application_id: Id da Aplicação (Application UID)
+ secret: Segredo (Secret)
+ secret_hashed:
+ scopes:
+ confidential: Confidential
+ callback_urls: urls de Callback
+ actions: Ações
+ not_defined:
+ authorizations:
+ buttons:
+ authorize: Autorizar
+ deny: Negar
+ error:
+ title: Ocorreu um erro
+ new:
+ title: Autorização necessária
+ prompt: Autorizar %{client_name} a usar sua conta?
+ able_to: Essa aplicação será capaz de
+ show:
+ title: Código de autorização
+ form_post:
+ title:
+ authorized_applications:
+ confirmations:
+ revoke: Você tem certeza?
+ buttons:
+ revoke: Revogar
+ index:
+ title: Suas aplicações autorizadas
+ application: Aplicação
+ created_at: Criado em
+ date_format: "%Y-%m-%d %H:%M:%S"
+ pre_authorization:
+ status: Pre-authorization
+ errors:
+ messages:
+ invalid_request:
+ unknown: A requisição não possui um parâmetro obrigatório, inclui um parâmetro
+ inválido ou está malformada.
+ missing_param: 'Missing required parameter: %{value}.'
+ request_not_authorized: Request need to be authorized. Required parameter
+ for authorizing request is missing or invalid.
+ invalid_code_challenge:
+ invalid_redirect_uri: A uri de redirecionamento incluída não é válida.
+ unauthorized_client: O cliente não está autorizado a realizar essa requisição
+ usando este método.
+ access_denied: O dono do recurso (resource owner) ou servidor de autorização
+ (authorization server) negou a requisição.
+ invalid_scope: O escopo requisitado é inválido, desconhecido ou malformado.
+ invalid_code_challenge_method:
+ zero:
+ one:
+ other:
+ server_error: O servidor de autorização (authorization server) encontrou uma
+ condição inesperada que o impediu de completar a requisição.
+ temporarily_unavailable: O servidor de autorização (authorization server)
+ não foi rapaz de processar a requisição devido a um problema tempoário de
+ sobrecarga ou manuntenção.
+ credential_flow_not_configured: Resource Owner Password Credentials flow falhou
+ porque o Doorkeeper.configure.resource_owner_from_credentials não foi configurado.
+ resource_owner_authenticator_not_configured: Resource Owner find falhou porque
+ o Doorkeeper.configure.resource_owner_authenticator não foi configurado.
+ admin_authenticator_not_configured: Access to admin panel is forbidden due
+ to Doorkeeper.configure.admin_authenticator being unconfigured.
+ unsupported_response_type: O servidor de autorização não suporta este tipo
+ de resposta.
+ unsupported_response_mode:
+ invalid_client: Autenticação do cliente falhou devido a um cliente desconhecido,
+ a falta de inclusão da autenticação do cliente, ou a um método não suportado
+ de autenticação.
+ invalid_grant: A permissão de autorização (authorization grant) provida é
+ inválida, expirada, revogada, não bate com a URI de redirecionamento usada
+ na requisição de autorização, ou foi dada a outro cliente.
+ unsupported_grant_type: O tipo de permissão de autorização (authorization
+ grant) não é suportado pelo servidor de autorização(authorization server)
+ The authorization grant type is not supported by the authorization server.
+ invalid_token:
+ revoked: O token de acesso (access token) foi revogado
+ expired: O token de acesso (access token) expirou
+ unknown: O token de acesso (access token) é inválido
+ revoke:
+ unauthorized: You are not authorized to revoke this token
+ forbidden_token:
+ missing_scope:
+ flash:
+ applications:
+ create:
+ notice: Aplicação criada.
+ destroy:
+ notice: Aplicação deletada.
+ update:
+ notice: Aplicação atualizada.
+ authorized_applications:
+ destroy:
+ notice: Aplicação revogada.
+ layouts:
+ admin:
+ title: Doorkeeper
+ nav:
+ oauth2_provider: Provedor OAuth2 (OAuth2 Provider)
+ applications: Aplicações
+ home: Home
+ application:
+ title: Autorização OAuth necessária
diff --git a/config/locales/translation.sv-FI.yml b/config/locales/translation.sv-FI.yml
index db0e54cc33..9a8a99b0b3 100644
--- a/config/locales/translation.sv-FI.yml
+++ b/config/locales/translation.sv-FI.yml
@@ -141,6 +141,22 @@ sv-FI:
restrict_dependent_destroy:
has_one: Kan inte ta bort post då beroende %{record} finns
has_many: Kan inte ta bort poster då beroende %{record} finns
+ models:
+ doorkeeper/application:
+ attributes:
+ redirect_uri:
+ fragment_present:
+ invalid_uri:
+ unspecified_scheme:
+ relative_uri:
+ secured_uri:
+ forbidden_uri:
+ scopes:
+ not_match_configured:
+ attributes:
+ doorkeeper/application:
+ name: Namn
+ redirect_uri:
datetime:
distance_in_words:
half_a_minute: en halv minut
@@ -351,3 +367,123 @@ sv-FI:
verification_failed: verifiering av reCAPTCHA misslyckades, försök igen.
recaptcha_unreachable: Oj, vi kunde inte validera ditt reCAPTCHA-svar. Var god
försök igen.
+ doorkeeper:
+ applications:
+ confirmations:
+ destroy: Är du säker?
+ buttons:
+ edit: Redigera
+ destroy:
+ submit: Skicka
+ cancel: Annullera
+ authorize:
+ form:
+ error:
+ help:
+ confidential:
+ redirect_uri:
+ blank_redirect_uri:
+ scopes:
+ edit:
+ title:
+ index:
+ title:
+ new:
+ name: Namn
+ callback_url:
+ confidential:
+ actions: Åtgärder
+ confidentiality:
+ 'yes': Ja
+ 'no': Nej
+ new:
+ title:
+ show:
+ title:
+ application_id:
+ secret:
+ secret_hashed:
+ scopes:
+ confidential:
+ callback_urls:
+ actions: Åtgärder
+ not_defined:
+ authorizations:
+ buttons:
+ authorize:
+ deny:
+ error:
+ title:
+ new:
+ title:
+ prompt:
+ able_to:
+ show:
+ title:
+ form_post:
+ title:
+ authorized_applications:
+ confirmations:
+ revoke: Är du säker?
+ buttons:
+ revoke:
+ index:
+ title:
+ application:
+ created_at:
+ date_format:
+ pre_authorization:
+ status:
+ errors:
+ messages:
+ invalid_request:
+ unknown:
+ missing_param:
+ request_not_authorized:
+ invalid_code_challenge:
+ invalid_redirect_uri:
+ unauthorized_client:
+ access_denied:
+ invalid_scope:
+ invalid_code_challenge_method:
+ zero:
+ one:
+ other:
+ server_error:
+ temporarily_unavailable:
+ credential_flow_not_configured:
+ resource_owner_authenticator_not_configured:
+ admin_authenticator_not_configured:
+ unsupported_response_type:
+ unsupported_response_mode:
+ invalid_client:
+ invalid_grant:
+ unsupported_grant_type:
+ invalid_token:
+ revoked:
+ expired:
+ unknown:
+ revoke:
+ unauthorized:
+ forbidden_token:
+ missing_scope:
+ flash:
+ applications:
+ create:
+ notice:
+ destroy:
+ notice:
+ update:
+ notice:
+ authorized_applications:
+ destroy:
+ notice:
+ layouts:
+ admin:
+ title:
+ nav:
+ oauth2_provider:
+ applications:
+ home: Hem
+ application:
+ title:
diff --git a/config/locales/translation.tr-TR.yml b/config/locales/translation.tr-TR.yml
index ce56653e18..379e8db76e 100644
--- a/config/locales/translation.tr-TR.yml
+++ b/config/locales/translation.tr-TR.yml
@@ -146,6 +146,22 @@ tr-TR:
restrict_dependent_destroy:
has_one: Bağlı bir %{record} bulunduğu için kayıt silinemiyor
has_many: Bağlı %{record} bulunduğu için kayıt silinemiyor
+ models:
+ doorkeeper/application:
+ attributes:
+ redirect_uri:
+ fragment_present:
+ invalid_uri:
+ unspecified_scheme:
+ relative_uri:
+ secured_uri:
+ forbidden_uri:
+ scopes:
+ not_match_configured:
+ attributes:
+ doorkeeper/application:
+ name: isim
+ redirect_uri:
datetime:
distance_in_words:
half_a_minute: yarım dakika
@@ -351,3 +367,123 @@ tr-TR:
notices:
error: Her iki alanı da doldurmalısınız.
success: İletişim e-postası başarıyla gönderildi.
+ doorkeeper:
+ applications:
+ confirmations:
+ destroy: Emin misiniz?
+ buttons:
+ edit: Düzenle
+ destroy:
+ submit: Gönder
+ cancel: İptal
+ authorize:
+ form:
+ error:
+ help:
+ confidential:
+ redirect_uri:
+ blank_redirect_uri:
+ scopes:
+ edit:
+ title:
+ index:
+ title:
+ new:
+ name: isim
+ callback_url:
+ confidential:
+ actions: Eylemler
+ confidentiality:
+ 'yes': Evet
+ 'no': Yok
+ new:
+ title:
+ show:
+ title:
+ application_id:
+ secret:
+ secret_hashed:
+ scopes:
+ confidential:
+ callback_urls:
+ actions: Eylemler
+ not_defined:
+ authorizations:
+ buttons:
+ authorize:
+ deny:
+ error:
+ title:
+ new:
+ title:
+ prompt:
+ able_to:
+ show:
+ title:
+ form_post:
+ title:
+ authorized_applications:
+ confirmations:
+ revoke: Emin misiniz?
+ buttons:
+ revoke:
+ index:
+ title:
+ application:
+ created_at:
+ date_format:
+ pre_authorization:
+ status:
+ errors:
+ messages:
+ invalid_request:
+ unknown:
+ missing_param:
+ request_not_authorized:
+ invalid_code_challenge:
+ invalid_redirect_uri:
+ unauthorized_client:
+ access_denied:
+ invalid_scope:
+ invalid_code_challenge_method:
+ zero:
+ one:
+ other:
+ server_error:
+ temporarily_unavailable:
+ credential_flow_not_configured:
+ resource_owner_authenticator_not_configured:
+ admin_authenticator_not_configured:
+ unsupported_response_type:
+ unsupported_response_mode:
+ invalid_client:
+ invalid_grant:
+ unsupported_grant_type:
+ invalid_token:
+ revoked:
+ expired:
+ unknown:
+ revoke:
+ unauthorized:
+ forbidden_token:
+ missing_scope:
+ flash:
+ applications:
+ create:
+ notice:
+ destroy:
+ notice:
+ update:
+ notice:
+ authorized_applications:
+ destroy:
+ notice:
+ layouts:
+ admin:
+ title:
+ nav:
+ oauth2_provider:
+ applications:
+ home: Ana sayfa
+ application:
+ title:
diff --git a/config/routes.rb b/config/routes.rb
index 5954d44591..274c494d1d 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -2,6 +2,7 @@
# rubocop:disable Metrics/BlockLength
Rails.application.routes.draw do
+ use_doorkeeper
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
devise_for(:users, controllers: {
@@ -203,6 +204,14 @@
resources :plans, only: %i[create show index]
resources :templates, only: [:index]
end
+
+ namespace :v2 do
+ get :heartbeat, controller: :base_api
+ get :me, controller: :base_api
+
+ resources :plans, only: %i[index show]
+ resources :templates, only: :index
+ end
end
namespace :paginable do
diff --git a/db/migrate/20251119131055_create_doorkeeper_tables.rb b/db/migrate/20251119131055_create_doorkeeper_tables.rb
new file mode 100644
index 0000000000..c7ee41b979
--- /dev/null
+++ b/db/migrate/20251119131055_create_doorkeeper_tables.rb
@@ -0,0 +1,98 @@
+# frozen_string_literal: true
+
+class CreateDoorkeeperTables < ActiveRecord::Migration[7.1]
+ def change
+ create_table :oauth_applications do |t|
+ t.string :name, null: false
+ t.string :uid, null: false
+ t.string :secret, null: false
+
+ # Remove `null: false` if you are planning to use grant flows
+ # that doesn't require redirect URI to be used during authorization
+ # like Client Credentials flow or Resource Owner Password.
+ t.text :redirect_uri, null: false
+ t.string :scopes, null: false, default: ''
+ t.boolean :confidential, null: false, default: true
+ t.timestamps null: false
+ end
+
+ add_index :oauth_applications, :uid, unique: true
+
+ create_table :oauth_access_grants do |t|
+ t.references :resource_owner, null: false
+ t.references :application, null: false
+ t.string :token, null: false
+ t.integer :expires_in, null: false
+ t.text :redirect_uri, null: false
+ t.string :scopes, null: false, default: ''
+ t.datetime :created_at, null: false
+ t.datetime :revoked_at
+ end
+
+ add_index :oauth_access_grants, :token, unique: true
+ add_foreign_key(
+ :oauth_access_grants,
+ :oauth_applications,
+ column: :application_id
+ )
+
+ create_table :oauth_access_tokens do |t|
+ t.references :resource_owner, index: true
+
+ # Remove `null: false` if you are planning to use Password
+ # Credentials Grant flow that doesn't require an application.
+ t.references :application, null: false
+
+ # If you use a custom token generator you may need to change this column
+ # from string to text, so that it accepts tokens larger than 255
+ # characters. More info on custom token generators in:
+ # https://github.com/doorkeeper-gem/doorkeeper/tree/v3.0.0.rc1#custom-access-token-generator
+ #
+ # t.text :token, null: false
+ t.string :token, null: false
+
+ t.string :refresh_token
+ t.integer :expires_in
+ t.string :scopes
+ t.datetime :created_at, null: false
+ t.datetime :revoked_at
+
+ # The authorization server MAY issue a new refresh token, in which case
+ # *the client MUST discard the old refresh token* and replace it with the
+ # new refresh token. The authorization server MAY revoke the old
+ # refresh token after issuing a new refresh token to the client.
+ # @see https://datatracker.ietf.org/doc/html/rfc6749#section-6
+ #
+ # Doorkeeper implementation: if there is a `previous_refresh_token` column,
+ # refresh tokens will be revoked after a related access token is used.
+ # If there is no `previous_refresh_token` column, previous tokens are
+ # revoked as soon as a new access token is created.
+ #
+ # Comment out this line if you want refresh tokens to be instantly
+ # revoked after use.
+ t.string :previous_refresh_token, null: false, default: ""
+ end
+
+ add_index :oauth_access_tokens, :token, unique: true
+
+ # See https://github.com/doorkeeper-gem/doorkeeper/issues/1592
+ if ActiveRecord::Base.connection.adapter_name == "SQLServer"
+ execute <<~SQL.squish
+ CREATE UNIQUE NONCLUSTERED INDEX index_oauth_access_tokens_on_refresh_token ON oauth_access_tokens(refresh_token)
+ WHERE refresh_token IS NOT NULL
+ SQL
+ else
+ add_index :oauth_access_tokens, :refresh_token, unique: true
+ end
+
+ add_foreign_key(
+ :oauth_access_tokens,
+ :oauth_applications,
+ column: :application_id
+ )
+
+ # Uncomment below to ensure a valid reference to the resource owner's table
+ add_foreign_key :oauth_access_grants, :users, column: :resource_owner_id
+ add_foreign_key :oauth_access_tokens, :users, column: :resource_owner_id
+ end
+end
\ No newline at end of file
diff --git a/db/schema.rb b/db/schema.rb
index 3b6036f2bf..f96170db11 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.1].define(version: 2025_01_15_102816) do
+ActiveRecord::Schema[7.1].define(version: 2025_11_19_131055) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -246,6 +246,48 @@
t.boolean "enabled", default: true
end
+ create_table "oauth_access_grants", force: :cascade do |t|
+ t.bigint "resource_owner_id", null: false
+ t.bigint "application_id", null: false
+ t.string "token", null: false
+ t.integer "expires_in", null: false
+ t.text "redirect_uri", null: false
+ t.string "scopes", default: "", null: false
+ t.datetime "created_at", null: false
+ t.datetime "revoked_at"
+ t.index ["application_id"], name: "index_oauth_access_grants_on_application_id"
+ t.index ["resource_owner_id"], name: "index_oauth_access_grants_on_resource_owner_id"
+ t.index ["token"], name: "index_oauth_access_grants_on_token", unique: true
+ end
+
+ create_table "oauth_access_tokens", force: :cascade do |t|
+ t.bigint "resource_owner_id"
+ t.bigint "application_id", null: false
+ t.string "token", null: false
+ t.string "refresh_token"
+ t.integer "expires_in"
+ t.string "scopes"
+ t.datetime "created_at", null: false
+ t.datetime "revoked_at"
+ t.string "previous_refresh_token", default: "", null: false
+ t.index ["application_id"], name: "index_oauth_access_tokens_on_application_id"
+ t.index ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true
+ t.index ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id"
+ t.index ["token"], name: "index_oauth_access_tokens_on_token", unique: true
+ end
+
+ create_table "oauth_applications", force: :cascade do |t|
+ t.string "name", null: false
+ t.string "uid", null: false
+ t.string "secret", null: false
+ t.text "redirect_uri", null: false
+ t.string "scopes", default: "", null: false
+ t.boolean "confidential", default: true, null: false
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["uid"], name: "index_oauth_applications_on_uid", unique: true
+ end
+
create_table "org_token_permissions", id: :serial, force: :cascade do |t|
t.integer "org_id"
t.integer "token_permission_type_id"
@@ -644,6 +686,10 @@
add_foreign_key "notes", "users"
add_foreign_key "notification_acknowledgements", "notifications"
add_foreign_key "notification_acknowledgements", "users"
+ add_foreign_key "oauth_access_grants", "oauth_applications", column: "application_id"
+ add_foreign_key "oauth_access_grants", "users", column: "resource_owner_id"
+ add_foreign_key "oauth_access_tokens", "oauth_applications", column: "application_id"
+ add_foreign_key "oauth_access_tokens", "users", column: "resource_owner_id"
add_foreign_key "org_token_permissions", "orgs"
add_foreign_key "org_token_permissions", "token_permission_types"
add_foreign_key "orgs", "languages"
diff --git a/spec/factories/identifier_schemes.rb b/spec/factories/identifier_schemes.rb
index 3e52d43b66..3e24252c61 100644
--- a/spec/factories/identifier_schemes.rb
+++ b/spec/factories/identifier_schemes.rb
@@ -32,5 +32,19 @@
identifier_scheme.update("#{identifier_scheme.all_context[idx]}": true)
end
end
+
+ %i[
+ authentication
+ orgs
+ plans
+ users
+ contributors
+ identification
+ research_outputs
+ ].each do |context|
+ trait :"for_#{context}" do
+ add_attribute(:"for_#{context}") { true }
+ end
+ end
end
end
diff --git a/spec/factories/oauth_access_grants.rb b/spec/factories/oauth_access_grants.rb
new file mode 100644
index 0000000000..2cd8dc8875
--- /dev/null
+++ b/spec/factories/oauth_access_grants.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+# == Schema Information
+#
+# Table name: oauth_access_grants
+#
+# id :integer not null, primary key
+# resource_owner_id :integer not null
+# application_id :integer not null
+# token :string not null
+# expires_in :integer
+# revoked_at :datetime
+# created_at :datetime not null
+# scopes :string not null
+#
+# Indexes
+#
+# index_oauth_access_grants_on_token (token)
+#
+# Foreign Keys
+#
+# fk_rails_... (resource_owner_id => users.id)
+# fk_rails_... (application_id => oauth_applications.id)
+
+FactoryBot.define do
+ factory :oauth_access_grant, class: 'doorkeeper/access_grant' do
+ token { SecureRandom.uuid }
+ expires_in { Faker::Number.number(digits: 8) }
+ scopes { Doorkeeper.config.default_scopes + Doorkeeper.config.optional_scopes }
+ redirect_uri { Faker::Internet.url }
+
+ trait :revoked do
+ revoked_at { 2.hours.ago }
+ end
+ end
+end
diff --git a/spec/factories/oauth_access_tokens.rb b/spec/factories/oauth_access_tokens.rb
new file mode 100644
index 0000000000..aa94d6b373
--- /dev/null
+++ b/spec/factories/oauth_access_tokens.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+# == Schema Information
+#
+# Table name: oauth_access_tokens
+#
+# id :integer not null, primary key
+# resource_owner_id :integer not null
+# application_id :integer not null
+# token :string not null
+# refresh_token :string
+# expires_in :integer
+# revoked_at :datetime
+# created_at :datetime not null
+# scopes :string not null
+# previous_refresh_token :string
+#
+# Indexes
+#
+# index_oauth_access_tokens_on_token (token)
+#
+# Foreign Keys
+#
+# fk_rails_... (resource_owner_id => users.id)
+# fk_rails_... (application_id => oauth_applications.id)
+
+FactoryBot.define do
+ factory :oauth_access_token, class: 'doorkeeper/access_token' do
+ token { SecureRandom.uuid }
+ refresh_token { SecureRandom.uuid }
+ expires_in { Faker::Number.number(digits: 8) }
+ scopes { Doorkeeper.config.default_scopes + Doorkeeper.config.optional_scopes }
+
+ trait :revoked do
+ revoked_at { 2.hours.ago }
+ end
+ end
+end
diff --git a/spec/factories/oauth_applications.rb b/spec/factories/oauth_applications.rb
new file mode 100644
index 0000000000..469dd66269
--- /dev/null
+++ b/spec/factories/oauth_applications.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+# == Schema Information
+#
+# Table name: oauth_application
+#
+# id: :integer
+# name: :string
+# uid: :string
+# secret: :string
+# redirect_uri: :text
+# scopes: :string
+# confidential: :boolean
+# created_at: :datetime
+# updated_at: :datetime
+
+FactoryBot.define do
+ factory :oauth_application, class: 'doorkeeper/application' do
+ name { Faker::Lorem.unique.word }
+ uid { SecureRandom.uuid }
+ secret { SecureRandom.uuid }
+ redirect_uri { "https://#{Faker::Internet.unique.domain_name}/callback" }
+ scopes { 'read' }
+ end
+end
diff --git a/spec/factories/research_domains.rb b/spec/factories/research_domains.rb
index 7d4017f924..23049903be 100644
--- a/spec/factories/research_domains.rb
+++ b/spec/factories/research_domains.rb
@@ -23,6 +23,5 @@
factory :research_domain do
identifier { SecureRandom.uuid }
label { Faker::Lorem.unique.word }
- uri { Faker::Internet.url }
end
end
diff --git a/spec/requests/api/v2/plans_controller_spec.rb b/spec/requests/api/v2/plans_controller_spec.rb
new file mode 100644
index 0000000000..bd951e42be
--- /dev/null
+++ b/spec/requests/api/v2/plans_controller_spec.rb
@@ -0,0 +1,126 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe Api::V2::PlansController do
+ include ApiHelper
+ include Mocks::ApiV2JsonSamples
+ include Webmocks
+ include IdentifierHelper
+
+ context 'OAuth (authorization_code grant type) — on behalf of a user' do
+ before do
+ @user = create(:user)
+ @client = create(:oauth_application)
+ token = mock_authorization_code_token(oauth_application: @client, user: @user).token
+
+ @headers = {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ Authorization: "Bearer #{token}"
+ }
+ end
+
+ def fetch_plans_json_response
+ get(api_v2_plans_path, headers: @headers)
+ expect(response).to render_template('api/v2/_standard_response')
+ expect(response).to render_template('api/v2/plans/index')
+ JSON.parse(response.body).with_indifferent_access
+ end
+
+ describe 'GET /api/v2/plans (index)' do
+ context 'an invalid API token is included' do
+ it 'returns a 401 and the expected Oauth 2.0 headers' do
+ # Swap actual token with a random string
+ @headers['Authorization'] = "Bearer #{SecureRandom.uuid}"
+ get(api_v2_plans_path, headers: @headers)
+
+ expect(response.code).to eql('401')
+ expect(response.body).to be_empty
+
+ # Expect Doorkeeper to return the standard OAuth 2.0 WWW-Authenticate header for invalid tokens
+ expect(response.headers['WWW-Authenticate']).to match(
+ /Bearer realm="Doorkeeper", error="invalid_token", error_description="The access token is invalid"/
+ )
+ end
+ end
+
+ context 'a valid API token is included' do
+ let(:json) { fetch_plans_json_response }
+ it 'returns a 200 and the expected response body' do
+ # Items array is empty
+ expect(json[:items]).to eq([])
+
+ # total_items reflects that nothing is returned
+ expect(json[:total_items]).to eq(0)
+
+ # Status code and message are correct
+ expect(json[:code]).to eq(200)
+ expect(json[:message]).to eq('OK')
+
+ # Application and source are present and sensible
+ expect(json[:application]).to eq(ApplicationService.application_name)
+ expect(json[:source]).to eq('GET /api/v2/plans')
+
+ # Time is present and parseable
+ expect { Time.iso8601(json[:time]) }.not_to raise_error
+
+ # Caller is included
+ expect(json[:caller]).to eq(@client.name)
+ end
+
+ it 'returns an empty array if no plans are available' do
+ # Items array is empty
+ expect(json[:items]).to eq([])
+
+ # total_items reflects that nothing is returned
+ expect(json[:total_items]).to eq(0)
+ end
+
+ it 'returns the expected plans' do
+ # See `app/policies/api/v2/plans_policy.rb for plans included/excluded via `GET api/v2/plans`
+
+ # Create the included plans
+ included_plans = [create(:plan, org: @user.org), create(:plan)]
+ included_plans[0].add_user!(@user.id, :creator)
+ # Add multiple roles for testing (ensure duplicate plans will not returned)
+ included_plans[1].add_user!(@user.id, :editor)
+ included_plans[1].add_user!(@user.id, :commenter)
+
+ # Created the excluded plans
+ create(:plan, :creator, org: @user.org)
+ inactive_plan = create(:plan, :creator)
+ inactive_plan.add_user!(@user.id, :editor)
+ Role.where(plan_id: inactive_plan.id, user_id: @user.id).update!(active: false)
+
+ expect(json[:items].length).to be(included_plans.length)
+
+ # Api::V2::PlanPresenter.identifier uses api_v2_plan_url(@plan) to set the "identifier".
+ # That url is constructed using `request.host` / "www.example.com"
+ # api_v2_plan_url(@plan) within this test will construct the url via
+ # default_url_options[:host] / "example.org"
+ # Because the urls are misaligned, we will only compare the paths here.
+ # TODO: Consider aligning default_url_options[:host] (in test.rb) with `request.host`
+ returned_identifiers = json[:items].map { |item| item[:dmp][:dmp_id][:identifier] }
+ returned_paths = returned_identifiers.map { |url| URI(url).path }
+ expected_paths = included_plans.map { |plan| api_v2_plan_path(plan) }
+ expect(returned_paths).to eq(expected_paths)
+ end
+
+ it 'allows for paging' do
+ original_page_size = Rails.configuration.x.application.api_max_page_size
+ Rails.configuration.x.application.api_max_page_size = 10
+
+ create_list(:plan, 11, :publicly_visible) do |plan|
+ plan.add_user!(@user.id, :commenter)
+ end
+ json = fetch_plans_json_response
+
+ test_paging(json: json, headers: @headers)
+
+ Rails.configuration.x.application.api_max_page_size = original_page_size
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/v2/templates_controller_spec.rb b/spec/requests/api/v2/templates_controller_spec.rb
new file mode 100644
index 0000000000..6b447d33a0
--- /dev/null
+++ b/spec/requests/api/v2/templates_controller_spec.rb
@@ -0,0 +1,120 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe Api::V2::TemplatesController do
+ include ApiHelper
+
+ before do
+ @user = create(:user)
+ @client = create(:oauth_application)
+ token = mock_authorization_code_token(oauth_application: @client, user: @user).token
+
+ @headers = {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ Authorization: "Bearer #{token}"
+ }
+ end
+
+ def fetch_templates_json_response
+ get(api_v2_templates_path, headers: @headers)
+ expect(response).to render_template('api/v2/_standard_response')
+ expect(response).to render_template('api/v2/templates/index')
+ JSON.parse(response.body).with_indifferent_access
+ end
+
+ describe 'GET /api/v2/templates (index)' do
+ context 'an invalid API token is included' do
+ it 'returns 401 if the token is invalid' do
+ @headers['Authorization'] = "Bearer #{SecureRandom.uuid}"
+ get(api_v2_templates_path, headers: @headers)
+
+ expect(response.code).to eql('401')
+ expect(response.body).to be_empty
+
+ # Expect Doorkeeper to return the standard OAuth 2.0 WWW-Authenticate header for invalid tokens
+ expect(response.headers['WWW-Authenticate']).to match(
+ /Bearer realm="Doorkeeper", error="invalid_token", error_description="The access token is invalid"/
+ )
+ end
+ end
+
+ context 'a valid API token is included' do
+ it 'returns a 200 and the expected response body' do
+ json = fetch_templates_json_response
+
+ # Items array is empty
+ expect(json[:items]).to eq([])
+
+ # total_items reflects that nothing is returned
+ expect(json[:total_items]).to eq(0)
+
+ # Status code and message are correct
+ expect(json[:code]).to eq(200)
+ expect(json[:message]).to eq('OK')
+
+ # Application and source are present and sensible
+ expect(json[:application]).to eq(ApplicationService.application_name)
+ expect(json[:source]).to eq('GET /api/v2/templates')
+
+ # Time is present and parseable
+ expect { Time.iso8601(json[:time]) }.not_to raise_error
+
+ # Caller is included
+ expect(json[:caller]).to eq(@client.name)
+ end
+
+ it 'returns an empty array if no templates are available' do
+ get(api_v2_templates_path, headers: @headers)
+
+ expect(response.code).to eql('200')
+ expect(response).to render_template('api/v2/_standard_response')
+ expect(response).to render_template('api/v2/templates/index')
+
+ json = JSON.parse(response.body).with_indifferent_access
+ expect(json[:items].empty?).to be(true)
+ expect(json[:errors].nil?).to be(true)
+ end
+
+ it 'returns the expected templates' do
+ # See `app/policies/api/v2/templates_policy.rb for templates included/excluded via `GET api/v2/templates`
+
+ # All included templates must be published and are either:
+ # - 1) organisationally_visible and template.org_id == user.org_id
+ # - 2) publicly_visible and customization of == nil
+
+ public_template = create(:template, :publicly_visible, published: true)
+
+ included_templates = [
+ public_template,
+ create(:template, :organisationally_visible, published: true, org: @user.org)
+ ]
+
+ # excluded_templates
+ # unpublished template
+ create(:template, :publicly_visible, published: false, org: @user.org)
+ # organisationally_visible and template.org_id != user.org_id
+ create(:template, :organisationally_visible, published: true)
+ # publicly_visible and customization of != nil
+ create(:template, :publicly_visible, published: true, customization_of: public_template.family_id)
+
+ json = fetch_templates_json_response
+
+ expect(json[:items].length).to be(2)
+ template_ids = json[:items].map { |item| item[:dmp_template][:template_id][:identifier] }
+ expect(template_ids).to match_array(included_templates.map { |t| t.id.to_s })
+ end
+
+ it 'allows for paging' do
+ original_page_size = Rails.configuration.x.application.api_max_page_size
+ Rails.configuration.x.application.api_max_page_size = 10
+ create_list(:template, 11, visibility: 1, published: true)
+ get(api_v2_templates_path, headers: @headers)
+
+ test_paging(json: JSON.parse(response.body), headers: @headers)
+ Rails.configuration.x.application.api_max_page_size = original_page_size
+ end
+ end
+ end
+end
diff --git a/spec/support/helpers/api.rb b/spec/support/helpers/api.rb
index c87931c12e..2a2398dfe7 100644
--- a/spec/support/helpers/api.rb
+++ b/spec/support/helpers/api.rb
@@ -18,4 +18,44 @@ def mock_authorization_for_user(user: nil)
Api::V1::BaseApiController.any_instance.stubs(:authorize_request).returns(true)
Api::V1::BaseApiController.any_instance.stubs(:client).returns(user)
end
+
+ # API V2+ - Oauth authorization_code grant flow (on behalf of a user)
+ def mock_authorization_code_token(oauth_application: create(:oauth_application), user: create(:user),
+ scopes: 'read')
+ create(:oauth_access_grant, application_id: oauth_application.id, resource_owner_id: user.id, scopes: scopes)
+ create(:oauth_access_token, application: oauth_application, resource_owner_id: user.id, scopes: scopes)
+ end
+
+ # Tests the standard pagination functionality
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
+ def test_paging(json: {}, headers: {})
+ json = json.with_indifferent_access
+ original = json[:items].first
+ if json[:next].present?
+ # Move to the next page
+ get(json[:next], headers: headers)
+ expect(response.code).to eql('200')
+ next_json = JSON.parse(response.body).with_indifferent_access
+ expect(next_json[:prev].present?).to be(true)
+ expect(next_json[:items].first).not_to eql(original)
+ # Move back to previous page
+ get(next_json[:prev], headers: headers)
+ expect(response.code).to eql('200')
+ prev_json = JSON.parse(response.body).with_indifferent_access
+ expect(prev_json[:items].first).to eql(original)
+ elsif json[:prev].present?
+ get(json[:prev], headers: headers)
+ expect(response.code).to eql('200')
+ prev_json = JSON.parse(response.body).with_indifferent_access
+ expect(prev_json[:next].present?).to be(true)
+ expect(next_json[:items].first).not_to eql(original)
+ get(prev_json[:next], headers: headers)
+ expect(response.code).to eql('200')
+ next_json = JSON.parse(response.body).with_indifferent_access
+ expect(next_json[:items].first).to eql(original)
+ else
+ raise StandardError, 'Expected to test API pagination but there are not enough items!'
+ end
+ end
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
end
diff --git a/spec/support/mocks/api_v2_json_samples.rb b/spec/support/mocks/api_v2_json_samples.rb
new file mode 100644
index 0000000000..aaec320811
--- /dev/null
+++ b/spec/support/mocks/api_v2_json_samples.rb
@@ -0,0 +1,215 @@
+# frozen_string_literal: true
+
+# Mock JSON submissions
+module Mocks
+ # Disabling rubocop checks here since its basically just large hashes and
+ # would be difficult to read if broken up into multiple smaller functions.
+ # One option might be to store them as .json files and then just load them here
+ # but we would lose the use of Faker
+
+ # rubocop:disable Metrics/ModuleLength, Metrics/MethodLength
+ module ApiV2JsonSamples
+ ROLES = %w[Investigation Project_administration Data_curation].freeze
+
+ def mock_identifier_schemes
+ create(:identifier_scheme, name: 'ror')
+ create(:identifier_scheme, name: 'fundref')
+ create(:identifier_scheme, name: 'orcid')
+ create(:identifier_scheme, name: 'grant')
+ end
+
+ def minimal_update_json
+ {
+ total_items: 1,
+ items: [
+ {
+ dmp: {
+ title: Faker::Lorem.sentence,
+ contact: {
+ mbox: Faker::Internet.email,
+ affiliation: { name: Faker::Movies::StarWars.planet }
+ },
+ dataset: [{
+ title: Faker::Lorem.sentence
+ }],
+ dmp_id: {
+ type: 'doi',
+ identifier: SecureRandom.uuid
+ }
+ }
+ }
+ ]
+ }.to_json
+ end
+
+ def minimal_create_json
+ {
+ dmp: {
+ title: Faker::Lorem.sentence,
+ contact: {
+ mbox: Faker::Internet.email,
+ affiliation: { name: Faker::Movies::StarWars.planet }
+ },
+ dataset: [{
+ title: Faker::Lorem.sentence
+ }],
+ extension: [
+ "#{ApplicationService.application_name.split('-').first}": {
+ template: {
+ id: Template.last.id,
+ title: Faker::Lorem.sentence
+ }
+ }
+ ]
+ }
+ }.to_json
+ end
+
+ # rubocop:disable Metrics/AbcSize
+ def complete_create_json(client: nil)
+ template = create(:template, :published, :publicly_visible)
+ lang = Language.all.pluck(:abbreviation).sample || 'en-UK'
+ ror_scheme = IdentifierScheme.find_or_create_by(name: 'ror')
+ fundref_scheme = IdentifierScheme.find_or_create_by(name: 'fundref')
+ ror = create(:identifier, identifiable: create(:org), identifier_scheme: ror_scheme)
+ fundref = create(:identifier, identifiable: create(:org), identifier_scheme: fundref_scheme)
+
+ contact = {
+ name: [
+ Faker::TvShows::Simpsons.character.split.first,
+ Faker::TvShows::Simpsons.character.split.last
+ ].join(' '),
+ email: Faker::Internet.email,
+ id: SecureRandom.uuid
+ }
+
+ {
+ dmp: {
+ created: 3.months.ago.to_formatted_s(:iso8601),
+ title: Faker::Lorem.sentence,
+ description: Faker::Lorem.paragraph,
+ language: Api::V1::LanguagePresenter.three_char_code(lang: lang),
+ ethical_issues_exist: %w[yes no unknown].sample,
+ ethical_issues_description: Faker::Lorem.paragraph,
+ ethical_issues_report: Faker::Internet.url,
+ dmp_id: {
+ type: client.present? ? client.name.downcase : 'other',
+ identifier: SecureRandom.uuid
+ },
+ contact: {
+ name: contact[:name],
+ mbox: contact[:email],
+ affiliation: {
+ name: ror.identifiable.name,
+ abbreviation: ror.identifiable.abbreviation,
+ region: Faker::Space.planet,
+ affiliation_id: {
+ type: 'ror',
+ identifier: ror.value
+ }
+ },
+ contact_id: {
+ type: 'orcid',
+ identifier: contact[:id]
+ }
+ },
+ contributor: [{
+ role: [
+ 'http://credit.niso.org/contributor-roles/project-administration',
+ 'http://credit.niso.org/contributor-roles/investigation',
+ 'other'
+ ],
+ name: Faker::Movies::StarWars.character,
+ mbox: Faker::Internet.email,
+ affiliation: {
+ name: Faker::Movies::StarWars.planet,
+ abbreviation: Faker::Lorem.word.upcase,
+ affiliation_id: {
+ type: 'ror',
+ identifier: SecureRandom.uuid
+ }
+ },
+ contributor_id: {
+ type: 'orcid',
+ identifier: SecureRandom.uuid
+ }
+ }, {
+ role: [
+ 'http://credit.niso.org/contributor-roles/investigation'
+ ],
+ name: contact[:name],
+ mbox: contact[:email],
+ affiliation: {
+ name: ror.identifiable.name,
+ abbreviation: ror.identifiable.abbreviation,
+ affiliation_id: {
+ type: 'ror',
+ identifier: ror.value
+ }
+ },
+ contributor_id: {
+ type: 'orcid',
+ identifier: contact[:id]
+ }
+ }],
+ project: [{
+ title: Faker::Lorem.sentence,
+ description: Faker::Lorem.paragraph,
+ start: 3.months.from_now.to_formatted_s(:iso8601),
+ end: 2.years.from_now.to_formatted_s(:iso8601),
+ funding: [{
+ name: fundref.identifiable.name,
+ funder_id: {
+ type: 'fundref',
+ identifier: fundref.value
+ },
+ grant_id: {
+ type: 'other',
+ identifier: SecureRandom.uuid
+ },
+ dmproadmap_funding_opportunity_id: {
+ type: 'other',
+ identifier: SecureRandom.uuid
+ },
+ funding_status: %w[planned rejected granted].sample
+ }]
+ }],
+ dataset: [{
+ title: Faker::Lorem.sentence,
+ description: Faker::Lorem.paragraph,
+ personal_data: %w[yes no unknown].sample,
+ sensitive_data: %w[yes no unknown].sample,
+ issued: 6.months.from_now.to_formatted_s(:iso8601),
+ dataset_id: {
+ type: 'url',
+ identifier: Faker::Internet.url
+ },
+ distribution: [{
+ title: Faker::Lorem.sentence,
+ byte_size: Faker::Number.number(digits: 6),
+ data_access: %w[open embargoed restricted closed].sample,
+ host: {
+ title: Faker::Company.name,
+ description: Faker::Lorem.paragraph,
+ url: Faker::Internet.url,
+ dmproadmap_host_id: {
+ type: 'url',
+ identifier: Faker::Internet.url
+ }
+ },
+ license: [
+ {
+ license_ref: 'http://spdx.org/licenses/CC0-1.0.json',
+ start_date: 6.months.from_now.to_formatted_s(:iso8601)
+ }
+ ]
+ }]
+ }],
+ dmproadmap_template: { id: template.family_id, title: template.title }
+ }
+ }.to_json
+ end
+ # rubocop:enable Metrics/AbcSize
+ end
+ # rubocop:enable Metrics/ModuleLength, Metrics/MethodLength
+end
diff --git a/spec/views/api/v2/_standard_response.json_jbuilder_spec.rb b/spec/views/api/v2/_standard_response.json_jbuilder_spec.rb
new file mode 100644
index 0000000000..2758d51d22
--- /dev/null
+++ b/spec/views/api/v2/_standard_response.json_jbuilder_spec.rb
@@ -0,0 +1,184 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'api/v2/_standard_response.json.jbuilder' do
+ before do
+ @application = Faker::Lorem.word
+ # @caller = Faker::Lorem.word
+ @url = Faker::Internet.url
+ @code = 200
+
+ assign :application, @application
+ # assign :caller, @caller
+
+ @response = OpenStruct.new(status: @code)
+ @request = Net::HTTPGenericRequest.new('GET', nil, nil, @url)
+ end
+
+ describe 'standard response items - Also the same as: GET /heartbeat' do
+ before do
+ render partial: 'api/v2/standard_response',
+ locals: { response: @response, request: @request }
+ @json = JSON.parse(rendered).with_indifferent_access
+ end
+
+ it 'includes the :code' do
+ expect(@json[:code]).to eql(@code)
+ end
+
+ it 'includes the :message' do
+ expect(@json[:message]).to eql(Rack::Utils::HTTP_STATUS_CODES[@code])
+ end
+
+ it 'includes the :time' do
+ expect(@json[:time].present?).to be(true)
+ end
+
+ it ':time is in UTC format' do
+ expect(Date.parse(@json[:time]).is_a?(Date)).to be(true)
+ end
+
+ # it 'includes the :caller' do
+ # expect(@json[:caller]).to eql(@caller)
+ # end
+
+ it 'includes the :source' do
+ expect(@json[:source].include?(@url)).to be(true)
+ end
+
+ it 'includes the :total_items' do
+ expect(@json[:total_items]).to be(0)
+ end
+ end
+
+ context 'responses with pagination' do
+ describe 'On the 1st page and there is only one page' do
+ before do
+ assign :page, 1
+ assign :per_page, 3
+
+ render partial: 'api/v2/standard_response',
+ locals: { response: @response, request: @request,
+ total_items: 3 }
+ @json = JSON.parse(rendered).with_indifferent_access
+ end
+
+ it 'shows the correct page number' do
+ expect(@json[:page]).to be(1)
+ end
+
+ it 'includes the per_page number' do
+ expect(@json[:per_page]).to be(3)
+ end
+
+ it 'includes the :total_items' do
+ expect(@json[:total_items]).to be(3)
+ end
+
+ it "does not show a 'prev' page link" do
+ expect(@json[:prev].present?).to be(false)
+ end
+
+ it "does not show a 'next' page link" do
+ expect(@json[:prev].present?).to be(false)
+ end
+ end
+
+ describe 'On the 1st page and there multiple pages' do
+ before do
+ assign :page, 1
+ assign :per_page, 3
+
+ render partial: 'api/v2/standard_response',
+ locals: { response: @response, request: @request,
+ total_items: 4 }
+ @json = JSON.parse(rendered).with_indifferent_access
+ end
+
+ it 'shows the correct page number' do
+ expect(@json[:page]).to be(1)
+ end
+
+ it 'includes the per_page number' do
+ expect(@json[:per_page]).to be(3)
+ end
+
+ it 'includes the :total_items' do
+ expect(@json[:total_items]).to be(4)
+ end
+
+ it "does not show a 'prev' page link" do
+ expect(@json[:prev].present?).to be(false)
+ end
+
+ it "does not show a 'next' page link" do
+ expect(@json[:next].present?).to be(true)
+ end
+ end
+
+ describe 'On the 2nd page and there more than 2 pages' do
+ before do
+ assign :page, 2
+ assign :per_page, 3
+
+ render partial: 'api/v2/standard_response',
+ locals: { response: @response, request: @request,
+ total_items: 7 }
+ @json = JSON.parse(rendered).with_indifferent_access
+ end
+
+ it 'shows the correct page number' do
+ expect(@json[:page]).to be(2)
+ end
+
+ it 'includes the per_page number' do
+ expect(@json[:per_page]).to be(3)
+ end
+
+ it 'includes the :total_items' do
+ expect(@json[:total_items]).to be(7)
+ end
+
+ it "does not show a 'prev' page link" do
+ expect(@json[:prev].present?).to be(true)
+ end
+
+ it "does not show a 'next' page link" do
+ expect(@json[:next].present?).to be(true)
+ end
+ end
+
+ describe 'On the last page' do
+ before do
+ assign :page, 2
+ assign :per_page, 3
+
+ render partial: 'api/v2/standard_response',
+ locals: { response: @response, request: @request,
+ total_items: 5 }
+ @json = JSON.parse(rendered).with_indifferent_access
+ end
+
+ it 'shows the correct page number' do
+ expect(@json[:page]).to be(2)
+ end
+
+ it 'includes the per_page number' do
+ expect(@json[:per_page]).to be(3)
+ end
+
+ it 'includes the :total_items' do
+ expect(@json[:total_items]).to be(5)
+ end
+
+ it "does not show a 'prev' page link" do
+ expect(@json[:prev].present?).to be(true)
+ end
+
+ it "does not show a 'next' page link" do
+ expect(@json[:next].present?).to be(false)
+ end
+ end
+ end
+end
diff --git a/spec/views/api/v2/contributors/_show.json.jbuilder_spec.rb b/spec/views/api/v2/contributors/_show.json.jbuilder_spec.rb
new file mode 100644
index 0000000000..c2652decaf
--- /dev/null
+++ b/spec/views/api/v2/contributors/_show.json.jbuilder_spec.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'api/v2/contributors/_show.json.jbuilder' do
+ before do
+ @plan = create(:plan)
+ scheme = create(:identifier_scheme, name: 'orcid')
+ @contact = create(:contributor, org: create(:org), plan: @plan, roles_count: 0,
+ data_curation: true)
+ @ident = create(:identifier, identifiable: @contact, value: Faker::Lorem.word,
+ identifier_scheme: scheme)
+ @contact.reload
+ end
+
+ describe 'includes all of the Contributor attributes' do
+ before do
+ render partial: 'api/v2/contributors/show', locals: { contributor: @contact }
+ @json = JSON.parse(rendered).with_indifferent_access
+ end
+
+ it 'includes the :name' do
+ expect(@json[:name]).to eql(@contact.name)
+ end
+
+ it 'includes the :mbox' do
+ expect(@json[:mbox]).to eql(@contact.email)
+ end
+
+ it 'includes the :role' do
+ expect(@json[:role].first.ends_with?('data-curation')).to be(true)
+ end
+
+ it 'includes :affiliation' do
+ expect(@json[:affiliation][:name]).to eql(@contact.org.name)
+ end
+
+ it 'includes :contributor_id' do
+ expect(@json[:contributor_id][:type]).to eql(@ident.identifier_format)
+ expect(@json[:contributor_id][:identifier]).to eql(@ident.value)
+ end
+
+ it 'ignores non-orcid identifiers :contributor_id' do
+ scheme = create(:identifier_scheme, name: 'shibboleth')
+ create(:identifier, value: Faker::Lorem.word, identifiable: @contact,
+ identifier_scheme: scheme)
+ @contact.reload
+ expect(@json[:contributor_id][:type]).to eql(@ident.identifier_format)
+ expect(@json[:contributor_id][:identifier]).to eql(@ident.value)
+ end
+ end
+
+ describe 'includes all of the Contact attributes' do
+ before do
+ render partial: 'api/v2/contributors/show', locals: { contributor: @contact,
+ is_contact: true }
+ @json = JSON.parse(rendered).with_indifferent_access
+ end
+
+ it 'includes the :name' do
+ expect(@json[:name]).to eql(@contact.name)
+ end
+
+ it 'includes the :mbox' do
+ expect(@json[:mbox]).to eql(@contact.email)
+ end
+
+ it 'does NOT include the :role' do
+ expect(@json[:role]).to be_nil
+ end
+
+ it 'includes :affiliation' do
+ expect(@json[:affiliation][:name]).to eql(@contact.org.name)
+ end
+
+ it 'includes :contact_id' do
+ expect(@json[:contact_id][:type]).to eql(@ident.identifier_format)
+ expect(@json[:contact_id][:identifier]).to eql(@ident.value)
+ end
+
+ it 'ignores non-orcid identifiers :contact_id' do
+ scheme = create(:identifier_scheme, name: 'shibboleth')
+ create(:identifier, value: Faker::Lorem.word, identifiable: @contact,
+ identifier_scheme: scheme)
+ @contact.reload
+ expect(@json[:contact_id][:type]).to eql(@ident.identifier_format)
+ expect(@json[:contact_id][:identifier]).to eql(@ident.value)
+ end
+ end
+end
diff --git a/spec/views/api/v2/datasets/_show.json.jbuilder_spec.rb b/spec/views/api/v2/datasets/_show.json.jbuilder_spec.rb
new file mode 100644
index 0000000000..fc1b7d4e7b
--- /dev/null
+++ b/spec/views/api/v2/datasets/_show.json.jbuilder_spec.rb
@@ -0,0 +1,196 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'api/v2/datasets/_show.json.jbuilder' do
+ context ':output is a ResearchOutput' do
+ describe 'includes all of the dataset attributes' do
+ before do
+ @research_output = create(:research_output, plan: create(:plan))
+ @presenter = Api::V2::ResearchOutputPresenter.new(output: @research_output)
+ end
+
+ describe 'base :dataset attributes' do
+ before do
+ render partial: 'api/v2/datasets/show', locals: { output: @research_output }
+ @json = JSON.parse(rendered).with_indifferent_access
+ end
+
+ it 'includes :type' do
+ expect(@json[:type]).to eql(@research_output.output_type)
+ end
+
+ it 'includes :title' do
+ expect(@json[:title]).to eql(@research_output.title)
+ end
+
+ it 'includes :description' do
+ expect(@json[:description]).to eql(@research_output.description)
+ end
+
+ it 'includes :personal_data' do
+ val = Api::V2::ApiPresenter.boolean_to_yes_no_unknown(value: @research_output.personal_data)
+ expect(@json[:personal_data]).to eql(val)
+ end
+
+ it 'includes :sensitive_data' do
+ val = Api::V2::ApiPresenter.boolean_to_yes_no_unknown(value: @research_output.sensitive_data)
+ expect(@json[:sensitive_data]).to eql(val)
+ end
+
+ it 'includes :issued' do
+ expect(@json[:issued]).to eql(@research_output.release_date.to_formatted_s(:iso8601))
+ end
+
+ it 'includes :preservation_statement' do
+ expect(@json[:preservation_statement]).to eql(@presenter.preservation_statement)
+ end
+
+ it 'includes :security_and_privacy' do
+ expect(@json[:security_and_privacy]).to eql(@presenter.security_and_privacy)
+ end
+
+ it 'includes :data_quality_assurance' do
+ expect(@json[:data_quality_assurance]).to eql(@presenter.data_quality_assurance)
+ end
+ end
+
+ describe ':distribution' do
+ before do
+ @repo = @research_output.repositories.first
+ @license = create(:license)
+ @research_output.license_id = @license.id
+
+ render partial: 'api/v2/datasets/show', locals: { output: @research_output }
+ @json = JSON.parse(rendered).with_indifferent_access
+ end
+
+ it 'includes :distributions' do
+ expect(@json[:distribution].any?).to be(true)
+ end
+
+ it 'includes :title' do
+ expected = "Anticipated distribution for #{@research_output.title}"
+ expect(@json[:distribution].first[:title]).to eql(expected)
+ end
+
+ it 'includes :byte_size' do
+ expect(@json[:distribution].first[:byte_size]).to eql(@research_output.byte_size)
+ end
+
+ it 'includes :data_access' do
+ expect(@json[:distribution].first[:data_access]).to eql(@research_output.access)
+ end
+
+ it 'includes host[:title]' do
+ expect(@json[:distribution].first[:host][:title]).to eql(@repo.name)
+ end
+
+ it 'includes host[:description]' do
+ expect(@json[:distribution].first[:host][:description]).to eql(@repo.description)
+ end
+
+ it 'includes host[:url]' do
+ expect(@json[:distribution].first[:host][:url]).to eql(@repo.homepage)
+ end
+
+ it 'includes host[:dmproadmap_host_id]' do
+ result = @json[:distribution].first[:host][:dmproadmap_host_id][:identifier]
+ expect(result).to eql(@repo.uri)
+ end
+
+ it 'includes license[:license_ref]' do
+ expect(@json[:distribution].first[:license].first[:license_ref]).to eql(@license.uri)
+ end
+
+ it 'includes license[:start_date]' do
+ expected = @research_output.release_date.to_formatted_s(:iso8601)
+ expect(@json[:distribution].first[:license].first[:start_date]).to eql(expected)
+ end
+ end
+
+ describe ':metadata' do
+ before do
+ @standard = create(:metadata_standard)
+ @research_output.metadata_standards << @standard
+
+ render partial: 'api/v2/datasets/show', locals: { output: @research_output }
+ @json = JSON.parse(rendered).with_indifferent_access
+ end
+
+ it 'includes :metadata' do
+ expect(@json[:metadata].any?).to be(true)
+ end
+
+ it 'includes :description' do
+ uri = @standard.uri
+ metadata = @json[:metadata].select { |ms| ms[:metadata_standard_id][:identifier] == uri }
+ expected = "#{@standard.title} - #{@standard.description}"
+ expect(metadata.first[:description].start_with?(expected)).to be(true)
+ expect(metadata.first[:metadata_standard_id].present?).to be(true)
+ expect(metadata.first[:metadata_standard_id][:type]).to eql('url')
+ expect(metadata.first[:metadata_standard_id][:identifier]).to eql(uri)
+ end
+ end
+
+ describe ':technical_resources' do
+ it 'is always an empty array because this has not been implemented' do
+ render partial: 'api/v2/datasets/show', locals: { output: @research_output }
+ @json = JSON.parse(rendered).with_indifferent_access
+ expect(@json[:technical_resource].any?).to be(false)
+ end
+ end
+
+ describe ':keyword' do
+ it 'includes the ResearchDomain' do
+ research_domain = create(:research_domain)
+ @research_output.plan.research_domain_id = research_domain.id
+ render partial: 'api/v2/datasets/show', locals: { output: @research_output }
+ @json = JSON.parse(rendered).with_indifferent_access
+ expect(@json[:keyword].any?).to be(true)
+ expect(@json[:keyword].include?(research_domain.label))
+ expect(@json[:keyword].include?("#{research_domain.identifier} - #{research_domain.label}"))
+ end
+
+ it 'is not included if no ResearchDomain is defined' do
+ render partial: 'api/v2/datasets/show', locals: { output: @research_output }
+ @json = JSON.parse(rendered).with_indifferent_access
+ expect(@json[:keyword].present?).to be(false)
+ end
+ end
+ end
+ end
+
+ context ':output is a Plan' do
+ describe 'includes all of the dataset attributes' do
+ before do
+ @plan = create(:plan)
+ @research_domain = create(:research_domain)
+ @plan.research_domain_id = @research_domain.id
+
+ render partial: 'api/v2/datasets/show', locals: { output: @plan }
+ @json = JSON.parse(rendered).with_indifferent_access
+ end
+
+ it 'includes :type' do
+ expect(@json[:type]).to eql('dataset')
+ end
+
+ it 'includes :title' do
+ expect(@json[:title]).to eql('Generic dataset')
+ end
+
+ it 'includes :description' do
+ expect(@json[:description]).to eql('No individual datasets have been defined for this DMP.')
+ end
+
+ describe ':keyword' do
+ it 'includes the ResearchDomain' do
+ expect(@json[:keyword].any?).to be(true)
+ expect(@json[:keyword].include?(@research_domain.label))
+ expect(@json[:keyword].include?("#{@research_domain.identifier} - #{@research_domain.label}"))
+ end
+ end
+ end
+ end
+end
diff --git a/spec/views/api/v2/error.json.jbuilder_spec.rb b/spec/views/api/v2/error.json.jbuilder_spec.rb
new file mode 100644
index 0000000000..ca2337ff6d
--- /dev/null
+++ b/spec/views/api/v2/error.json.jbuilder_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'api/v2/error.json.jbuilder' do
+ before do
+ @url = Faker::Internet.url
+ @code = [200, 400, 404, 500].sample
+ @errors = [Faker::Lorem.sentence, Faker::Lorem.sentence]
+
+ assign :payload, { message: @errors }
+
+ @resp = OpenStruct.new(status: @code)
+ @req = Net::HTTPGenericRequest.new('GET', nil, nil, @url)
+
+ render template: 'api/v2/error', locals: { response: @resp, request: @req }
+ @json = JSON.parse(rendered).with_indifferent_access
+ end
+
+ describe 'error responses from controllers' do
+ it 'renders the standard_response partial' do
+ expect(response).to render_template(partial: 'api/v2/_standard_response')
+ end
+
+ it ':errors contains an array of error messages' do
+ expect(@json[:message]).to eql(@errors)
+ end
+ end
+end
diff --git a/spec/views/api/v2/heartbeat.json.jbuilder_spec.rb b/spec/views/api/v2/heartbeat.json.jbuilder_spec.rb
new file mode 100644
index 0000000000..1808117b19
--- /dev/null
+++ b/spec/views/api/v2/heartbeat.json.jbuilder_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'api/v2/heartbeat.json.jbuilder' do
+ before do
+ render template: 'api/v2/heartbeat', locals: { response: @resp, request: @req }
+ @json = JSON.parse(rendered).with_indifferent_access
+ end
+
+ it 'renders the _standard_response template' do
+ expect(response).to render_template('api/v2/_standard_response')
+ end
+
+ it ':items array to be empty' do
+ expect(@json[:items]).to eql([])
+ end
+end
diff --git a/spec/views/api/v2/identifiers/_show.json.jbuilder_spec.rb b/spec/views/api/v2/identifiers/_show.json.jbuilder_spec.rb
new file mode 100644
index 0000000000..602169fd75
--- /dev/null
+++ b/spec/views/api/v2/identifiers/_show.json.jbuilder_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'api/v2/identifiers/_show.json.jbuilder' do
+ before do
+ @scheme = create(:identifier_scheme)
+ @identifier = create(:identifier, value: Faker::Lorem.word,
+ identifier_scheme: @scheme)
+ render partial: 'api/v2/identifiers/show', locals: { identifier: @identifier }
+ @json = JSON.parse(rendered).with_indifferent_access
+ end
+
+ describe 'includes all of the identifier attributes' do
+ it 'includes :type' do
+ expect(@json[:type]).to eql(@identifier.identifier_format)
+ end
+
+ it 'includes :identifier' do
+ expect(@json[:identifier]).to eql(@identifier.value)
+ end
+ end
+end
diff --git a/spec/views/api/v2/orgs/_show.json.jbuilder_spec.rb b/spec/views/api/v2/orgs/_show.json.jbuilder_spec.rb
new file mode 100644
index 0000000000..5480ae0ee1
--- /dev/null
+++ b/spec/views/api/v2/orgs/_show.json.jbuilder_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'api/v2/orgs/_show.json.jbuilder' do
+ before do
+ scheme = create(:identifier_scheme, name: 'ror')
+ @org = create(:org)
+ @ident = create(:identifier, value: Faker::Lorem.word, identifiable: @org,
+ identifier_scheme: scheme)
+ @org.reload
+ render partial: 'api/v2/orgs/show', locals: { org: @org }
+ @json = JSON.parse(rendered).with_indifferent_access
+ end
+
+ describe 'includes all of the org attributes' do
+ it 'includes :name' do
+ expect(@json[:name]).to eql(@org.name)
+ end
+
+ it 'includes :abbreviation' do
+ expect(@json[:abbreviation]).to eql(@org.abbreviation)
+ end
+
+ it 'includes :region' do
+ expect(@json[:region]).to eql(@org.region.abbreviation)
+ end
+
+ it 'includes :affiliation_id' do
+ expect(@json[:affiliation_id][:type]).to eql(@ident.identifier_format)
+ expect(@json[:affiliation_id][:identifier]).to eql(@ident.value)
+ end
+
+ it 'uses the ROR over the FundRef :affiliation_id' do
+ scheme = create(:identifier_scheme, name: 'fundref')
+ create(:identifier, value: Faker::Lorem.word, identifiable: @org,
+ identifier_scheme: scheme)
+ @org.reload
+ expect(@json[:affiliation_id][:type]).to eql(@ident.identifier_format)
+ expect(@json[:affiliation_id][:identifier]).to eql(@ident.value)
+ end
+ end
+end
diff --git a/spec/views/api/v2/plans/_cost.json.jbuilder_spec.rb b/spec/views/api/v2/plans/_cost.json.jbuilder_spec.rb
new file mode 100644
index 0000000000..712e9300e9
--- /dev/null
+++ b/spec/views/api/v2/plans/_cost.json.jbuilder_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'api/v2/plans/_cost.json.jbuilder' do
+ before do
+ # TODO: Implement this once the Currency question and Cost theme are in place
+ # and the PlanPresenter is extracting the info
+ @cost = {
+ title: Faker::Lorem.sentence,
+ description: Faker::Lorem.paragraph,
+ currency_code: Faker::Currency.code,
+ value: Faker::Number.decimal(l_digits: 2)
+ }.with_indifferent_access
+
+ render partial: 'api/v2/plans/cost', locals: { cost: @cost }
+ @json = JSON.parse(rendered).with_indifferent_access
+ end
+
+ describe 'includes all of the cost attributes' do
+ it 'includes :title' do
+ expect(@json[:title]).to eql(@cost[:title])
+ end
+
+ it 'includes :description' do
+ expect(@json[:description]).to eql(@cost[:description])
+ end
+
+ it 'includes :currency_code' do
+ expect(@json[:currency_code]).to eql(@cost[:currency_code])
+ end
+
+ it 'includes :value' do
+ expect(@json[:value]).to eql(@cost[:value])
+ end
+ end
+end
diff --git a/spec/views/api/v2/plans/_funding.json.jbuilder_spec.rb b/spec/views/api/v2/plans/_funding.json.jbuilder_spec.rb
new file mode 100644
index 0000000000..e764e142b3
--- /dev/null
+++ b/spec/views/api/v2/plans/_funding.json.jbuilder_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'api/v2/plans/_funding.json.jbuilder' do
+ before do
+ @funder = create(:org, :funder)
+ create(:identifier, identifiable: @funder,
+ identifier_scheme: create(:identifier_scheme, name: 'fundref'))
+ @funder.reload
+ @plan = create(:plan, funder: @funder, org: create(:org), identifier: SecureRandom.uuid)
+ create(:identifier, identifiable: @plan.org,
+ identifier_scheme: create(:identifier_scheme, name: 'ror'))
+ @grant = create(:identifier, identifiable: @plan)
+ @plan.update(grant_id: @grant.id, funding_status: 'funded')
+ @plan.reload
+
+ render partial: 'api/v2/plans/funding', locals: { plan: @plan }
+ @json = JSON.parse(rendered).with_indifferent_access
+ end
+
+ describe 'includes all of the funding attributes' do
+ it 'includes :name' do
+ expect(@json[:name]).to eql(@funder.name)
+ end
+
+ it 'includes :funding_status' do
+ expected = Api::V1::FundingPresenter.status(plan: @plan)
+ expect(@json[:funding_status]).to eql(expected)
+ end
+
+ it 'includes :funder_ids' do
+ id = @funder.identifiers.first
+ expect(@json[:funder_id][:type]).to eql(id.identifier_format)
+ expect(@json[:funder_id][:identifier]).to eql(id.value)
+ end
+
+ it 'includes :dmproadmap_funding_opportunity_identifier' do
+ identifier = @plan.identifier
+ expect(@json[:dmproadmap_funding_opportunity_id][:type]).to eql('other')
+ expect(@json[:dmproadmap_funding_opportunity_id][:identifier]).to eql(identifier)
+ end
+
+ it 'includes :grant_ids' do
+ expect(@json[:grant_id][:type]).to eql(@grant.identifier_format)
+ expect(@json[:grant_id][:identifier]).to eql(@grant.value)
+ end
+
+ it 'includes :dmproadmap_funded_affiliations' do
+ org = @plan.org
+ expect(@json[:dmproadmap_funded_affiliations].any?).to be(true)
+ affil = @json[:dmproadmap_funded_affiliations].last
+ expect(affil[:name]).to eql(org.name)
+ expect(affil[:affiliation_id][:type]).to eql(org.identifiers.last.identifier_format)
+ expect(affil[:affiliation_id][:identifier]).to eql(org.identifiers.last.value)
+ end
+ end
+end
diff --git a/spec/views/api/v2/plans/_project.json.jbuilder_spec.rb b/spec/views/api/v2/plans/_project.json.jbuilder_spec.rb
new file mode 100644
index 0000000000..53af088379
--- /dev/null
+++ b/spec/views/api/v2/plans/_project.json.jbuilder_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'api/v2/plans/_project.json.jbuilder' do
+ before do
+ @plan = build(:plan, funder: build(:org, :funder))
+ render partial: 'api/v2/plans/project', locals: { plan: @plan }
+ @json = JSON.parse(rendered).with_indifferent_access
+ end
+
+ describe 'includes all of the project attributes' do
+ it 'includes :title' do
+ expect(@json[:title]).to eql(@plan.title)
+ end
+
+ it 'includes :description' do
+ expect(@json[:description]).to eql(@plan.description)
+ end
+
+ it 'includes :start' do
+ expect(@json[:start]).to eql(@plan.start_date.to_formatted_s(:iso8601))
+ end
+
+ it 'includes :end' do
+ expect(@json[:end]).to eql(@plan.end_date.to_formatted_s(:iso8601))
+ end
+
+ it 'includes the :funder' do
+ expect(@json[:funding].length).to be(1)
+ end
+ end
+end
diff --git a/spec/views/api/v2/plans/_show.json.jbuilder_spec.rb b/spec/views/api/v2/plans/_show.json.jbuilder_spec.rb
new file mode 100644
index 0000000000..989a2f638b
--- /dev/null
+++ b/spec/views/api/v2/plans/_show.json.jbuilder_spec.rb
@@ -0,0 +1,113 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'api/v2/plans/_show.json.jbuilder' do
+ before do
+ Rails.configuration.x.madmp.enable_dmp_id_registration = true
+
+ @plan = create(:plan)
+ @data_contact = create(:contributor, data_curation: true, plan: @plan)
+ @pi = create(:contributor, investigation: true, plan: @plan)
+ @plan.contributors = [@data_contact, @pi]
+ create(:identifier, identifiable: @plan)
+
+ # Create an Api Client and connect it to the Plan
+ @client = create(:api_client)
+ scheme = create(:identifier_scheme, :for_plans, name: @client.name.downcase)
+ @client_identifier = create(:identifier, identifier_scheme: scheme, identifiable: @plan)
+
+ @plan.save
+ @plan.reload
+ @presenter = Api::V2::PlanPresenter.new(plan: @plan)
+ end
+
+ describe 'includes all of the DMP attributes' do
+ before do
+ render partial: 'api/v2/plans/show', locals: { client: @client, plan: @plan }
+ @json = JSON.parse(rendered).with_indifferent_access
+ end
+
+ it 'includes the :title' do
+ expect(@json[:title]).to eql(@plan.title)
+ end
+
+ it 'includes the :description' do
+ expect(@json[:description]).to eql(@plan.description)
+ end
+
+ it 'includes the :language' do
+ expected = Api::V1::LanguagePresenter.three_char_code(
+ lang: LocaleService.default_locale
+ )
+ expect(@json[:language]).to eql(expected)
+ end
+
+ it 'includes the :created' do
+ expect(@json[:created]).to eql(@plan.created_at.to_formatted_s(:iso8601))
+ end
+
+ it 'includes the :modified' do
+ expect(@json[:modified]).to eql(@plan.updated_at.to_formatted_s(:iso8601))
+ end
+
+ it 'includes :ethical_issues' do
+ expected = Api::V1::ConversionService.boolean_to_yes_no_unknown(@plan.ethical_issues)
+ expect(@json[:ethical_issues_exist]).to eql(expected)
+ end
+
+ it 'includes :ethical_issues_description' do
+ expect(@json[:ethical_issues_description]).to eql(@plan.ethical_issues_description)
+ end
+
+ it 'includes :ethical_issues_report' do
+ expect(@json[:ethical_issues_report]).to eql(@plan.ethical_issues_report)
+ end
+
+ it 'returns the URL of the plan as the :dmp_id if no DMP ID is defined' do
+ expected = Rails.application.routes.url_helpers.api_v2_plan_url(@plan)
+ expect(@json[:dmp_id][:type]).to eql('url')
+ expect(@json[:dmp_id][:identifier]).to eql(expected)
+ end
+
+ it 'includes the :contact' do
+ expect(@json[:contact][:mbox]).to eql(@data_contact.email)
+ end
+
+ it 'includes the :contributors' do
+ emails = @json[:contributor].pluck(:mbox)
+ expect(emails.include?(@pi.email)).to be(true)
+ end
+
+ # TODO: make sure this is working once the new Cost theme and Currency
+ # question type have been implemented
+ it 'includes the :cost' do
+ expect(@json[:cost]).to be_nil
+ end
+
+ it 'includes the :project' do
+ expect(@json[:project].length).to be(1)
+ end
+
+ it 'includes the :dataset' do
+ expect(@json[:dataset].length).to be(1)
+ end
+ end
+
+ describe 'when the system mints DMP IDs', skip: 'DmpIdService not implemented' do
+ before do
+ scheme = create(:identifier_scheme)
+ DmpIdService.expects(:identifier_scheme).at_least(1).returns(scheme)
+ @doi = create(:identifier, value: '10.9999/123abc.zy/x23', identifiable: @plan,
+ identifier_scheme: scheme)
+ @plan.reload
+ render partial: 'api/v2/plans/show', locals: { client: @client, plan: @plan }
+ @json = JSON.parse(rendered).with_indifferent_access
+ end
+
+ it 'returns the DMP ID for the :dmp_id if one is present' do
+ expect(@json[:dmp_id][:type]).to eql('doi')
+ expect(@json[:dmp_id][:identifier]).to eql(@doi.value)
+ end
+ end
+end
diff --git a/spec/views/api/v2/plans/index.json.jbuilder_spec.rb b/spec/views/api/v2/plans/index.json.jbuilder_spec.rb
new file mode 100644
index 0000000000..5d47770c52
--- /dev/null
+++ b/spec/views/api/v2/plans/index.json.jbuilder_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'api/v2/plans/index.json.jbuilder' do
+ before do
+ @plan = create(:plan)
+
+ @client = create(:api_client)
+ @items = [@plan]
+ @total_items = 1
+
+ render template: 'api/v2/plans/index'
+ @json = JSON.parse(rendered).with_indifferent_access
+ end
+
+ it 'renders the _standard_response template' do
+ expect(response).to render_template('api/v2/_standard_response')
+ end
+
+ it ':items array to be empty' do
+ expect(@json[:items].length).to be(1)
+ expect(@json[:items].first[:dmp][:title]).to eql(@plan.title)
+ end
+end
diff --git a/spec/views/api/v2/templates/index.json.jbuilder_spec.rb b/spec/views/api/v2/templates/index.json.jbuilder_spec.rb
new file mode 100644
index 0000000000..99b35375ec
--- /dev/null
+++ b/spec/views/api/v2/templates/index.json.jbuilder_spec.rb
@@ -0,0 +1,78 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+describe 'api/v2/templates/index.json.jbuilder' do
+ before do
+ @application = Faker::Lorem.word
+ @url = Faker::Internet.url
+ @code = [200, 400, 404, 500].sample
+
+ @template1 = create(:template, :published, org: create(:org), phases: 1)
+ @template2 = create(:template, :published)
+
+ assign :server, @application
+ assign :items, [@template1, @template2]
+
+ @resp = OpenStruct.new(status: @code)
+ @req = Net::HTTPGenericRequest.new('GET', nil, nil, @url)
+ end
+
+ describe 'includes all of the Template attributes' do
+ before do
+ render template: 'api/v2/templates/index',
+ locals: { response: @resp, request: @req }
+ @json = JSON.parse(rendered).with_indifferent_access
+
+ @template = @json[:items].first[:dmp_template]
+ end
+
+ it 'includes both templates' do
+ expect(@json[:items].length).to be(2)
+ end
+
+ it 'includes the :title' do
+ expect(@template[:title]).to eql(@template1.title)
+ end
+
+ it 'includes the :description' do
+ expect(@template[:description]).to eql(@template1.description)
+ end
+
+ it 'includes the :version' do
+ expect(@template[:version]).to eql(@template1.version)
+ end
+
+ it 'includes the :created' do
+ expect(@template[:created]).to eql(@template1.created_at.to_formatted_s(:iso8601))
+ end
+
+ it 'includes the :modified' do
+ expect(@template[:modified]).to eql(@template1.updated_at.to_formatted_s(:iso8601))
+ end
+
+ it 'includes the :affiliation' do
+ expect(@template[:affiliation][:name]).to eql(@template1.org.name)
+ end
+
+ it 'includes the :template_ids' do
+ expect(@template[:template_id][:identifier]).to eql(@template1.id.to_s)
+ expect(@template[:template_id][:type]).to eql('other')
+ end
+
+ # The show_url parameter is either false or not included
+ it 'includes the :phases' do
+ expect(@json[:items].first[:dmp_template][:phases]).to be_nil
+ end
+ end
+
+ # The show_url parameter is true
+ describe 'when the show_phases url parameter is true' do
+ before do
+ @show_phases = true
+ render template: 'api/v2/templates/index',
+ locals: { response: @resp, request: @req, show_phases: @show_phases }
+ @json = JSON.parse(rendered).with_indifferent_access
+ end
+ end
+end