diff --git a/Makefile b/Makefile index ae8037c67e6..e7b046ec28a 100755 --- a/Makefile +++ b/Makefile @@ -156,7 +156,8 @@ locales: msgfmt -o modules/timepoint_list/locale/ja/LC_MESSAGES/timepoint_list.mo modules/timepoint_list/locale/ja/LC_MESSAGES/timepoint_list.po msgfmt -o modules/timepoint_list/locale/es/LC_MESSAGES/timepoint_list.mo modules/timepoint_list/locale/es/LC_MESSAGES/timepoint_list.po msgfmt -o modules/user_accounts/locale/ja/LC_MESSAGES/user_accounts.mo modules/user_accounts/locale/ja/LC_MESSAGES/user_accounts.po - + msgfmt -o modules/user_accounts/locale/hi/LC_MESSAGES/user_accounts.mo modules/user_accounts/locale/hi/LC_MESSAGES/user_accounts.po + npx i18next-conv -l hi -s modules/user_accounts/locale/hi/LC_MESSAGES/user_accounts.po -t modules/user_accounts/locale/hi/LC_MESSAGES/user_accounts.json acknowledgements: modules/acknowledgements/locale/ja/LC_MESSAGES/acknowledgements.mo target=acknowledgements npm run compile diff --git a/locale/hi/LC_MESSAGES/loris.po b/locale/hi/LC_MESSAGES/loris.po index e19c9f495a2..e79ea5fb478 100644 --- a/locale/hi/LC_MESSAGES/loris.po +++ b/locale/hi/LC_MESSAGES/loris.po @@ -126,6 +126,24 @@ msgstr "नहीं" msgid "N/A" msgstr "लागू नहीं" +msgid "Save" +msgstr "सहेजें" + +msgid "Reset" +msgstr "रीसेट करें" + +msgid "Back" +msgstr "वापस" + +msgid "None" +msgstr "कोई नहीं" + +msgid "Y" +msgstr "हाँ" + +msgid "N" +msgstr "नहीं" + msgid "Create" msgstr "बनाएँ" @@ -165,12 +183,21 @@ msgstr "डीसीसीआईडी" msgid "Visit Label" msgstr "दौरे का लेबल" +msgid "Email" +msgstr "ईमेल" + msgid "Site" msgstr "साइट" +msgid "Sites" +msgstr "साइट्स" + msgid "Project" msgstr "परियोजना" +msgid "Projects" +msgstr "प्रोजेक्ट्स" + msgid "Candidate Registration Project" msgstr "उम्मीदवार पंजीकरण परियोजना" @@ -223,6 +250,9 @@ msgstr "भ्रमण" msgid "An error occured while loading the page." msgstr "पृष्ठ लोड करते समय एक त्रुटि हुई।" +msgid "Active" +msgstr "सक्रिय" + msgid "Entity Type" msgstr "इकाई प्रकार" @@ -235,12 +265,6 @@ msgstr "भाषा" msgid "Ethnicity" msgstr "जातीयता" -msgid "Save" -msgstr "सहेजें" - -msgid "Reset" -msgstr "रीसेट करें" - # Data table strings msgid "{{pageCount}} rows displayed of {{totalCount}}." msgstr "{{totalCount}} में से {{pageCount}} पंक्तियाँ प्रदर्शित" @@ -306,12 +330,18 @@ msgstr "ईमेल पता" msgid "New Password" msgstr "नया पासवर्ड" +msgid "Password" +msgstr "पासवर्ड" + msgid "Confirm Password" msgstr "पासवर्ड की पुष्टि करें" msgid "Email address is required" msgstr "ईमेल पता आवश्यक है" +msgid "Email address cannot contain any of the following characters: <, >, &, and \"" +msgstr "ईमेल पता निम्नलिखित किसी भी वर्ण को नहीं शामिल कर सकता: <, >, &, और \"" + msgid "The password must be at least 8 characters long." msgstr "पासवर्ड कम से कम 8 अक्षरों का होना चाहिए।" @@ -370,9 +400,6 @@ msgstr "पूर्ण" msgid "Instruments" msgstr "उपकरण" -msgid "None" -msgstr "कोई नहीं" - msgid "Partial" msgstr "आंशिक" diff --git a/locale/loris.pot b/locale/loris.pot index 139852bb837..b0ade86d2ee 100644 --- a/locale/loris.pot +++ b/locale/loris.pot @@ -125,6 +125,24 @@ msgstr "" msgid "N/A" msgstr "" +msgid "Save" +msgstr "" + +msgid "Reset" +msgstr "" + +msgid "Back" +msgstr "" + +msgid "None" +msgstr "" + +msgid "Y" +msgstr "" + +msgid "N" +msgstr "" + msgid "Create" msgstr "" @@ -167,15 +185,24 @@ msgstr "" msgid "Visit Label" msgstr "" +msgid "Email" +msgstr "" + msgid "Site" msgstr "" +msgid "Sites" +msgstr "" + msgid "Module" msgstr "" msgid "Project" msgstr "" +msgid "Projects" +msgstr "" + msgid "Candidate Registration Project" msgstr "" @@ -231,6 +258,9 @@ msgstr "" msgid "An error occured while loading the page." msgstr "" +msgid "Active" +msgstr "" + msgid "Entity Type" msgstr "" @@ -243,12 +273,6 @@ msgstr "" msgid "Ethnicity" msgstr "" -msgid "Save" -msgstr "" - -msgid "Reset" -msgstr "" - # Data table strings msgid "{{pageCount}} rows displayed of {{totalCount}}." msgstr "" @@ -314,12 +338,18 @@ msgstr "" msgid "New Password" msgstr "" +msgid "Password" +msgstr "" + msgid "Confirm Password" msgstr "" msgid "Email address is required" msgstr "" +msgid "Email address cannot contain any of the following characters: <, >, &, and \"" +msgstr "" + msgid "The password must be at least 8 characters long." msgstr "" @@ -334,6 +364,7 @@ msgstr "" msgid "We suggest using a password manager to generate one for you." msgstr "" + msgid "Total" msgstr "" @@ -387,9 +418,6 @@ msgid "Instrument" msgid_plural "Instruments" msgstr[0] "" -msgid "None" -msgstr "" - msgid "Partial" msgstr "" diff --git a/modules/user_accounts/jsx/userAccountsIndex.js b/modules/user_accounts/jsx/userAccountsIndex.js index 56d491d69ea..b121c25ea8a 100644 --- a/modules/user_accounts/jsx/userAccountsIndex.js +++ b/modules/user_accounts/jsx/userAccountsIndex.js @@ -4,6 +4,7 @@ import PropTypes from 'prop-types'; import i18n from 'I18nSetup'; import {withTranslation} from 'react-i18next'; +import hiStrings from '../locale/hi/LC_MESSAGES/user_accounts.json'; import Loader from 'Loader'; import FilterableDataTable from 'FilterableDataTable'; @@ -16,13 +17,17 @@ import FilterableDataTable from 'FilterableDataTable'; * * When clicking on the Add User button or a Username, this component redirects * the user to a form that allows them to add or edit a user. + * + * @param {object} props - React component properties */ class UserAccountsIndex extends Component { /** * {@inheritdoc} + * + * @param props */ - constructor() { - super(); + constructor(props) { + super(props); this.state = { data: {}, @@ -69,53 +74,60 @@ class UserAccountsIndex extends Component { * @return {*} a formated table cell for a given column */ formatColumn(column, cell, row) { + const {t} = this.props; let url; let result = {cell}; switch (column) { - case 'Site': - // If user has multiple sites, join array of sites into string + case t('Site', {ns: 'loris'}): result = ( - {cell - .map((centerId) => this.state.data.fieldOptions.sites[centerId]) - .join(', ')} + + {cell + .map((centerId) => this.state.data.fieldOptions.sites[centerId]) + .join(', ')} ); if (cell.length === 0) { result = ( - This user has no site affiliations + + {t('This user has no site affiliations', {ns: 'user_accounts'})} + ); } break; - case 'Project': - // If user has multiple projects, join array of sites into string + case t('Project', {ns: 'loris'}): result = ( - {cell.map( - (projectId) => this.state.data.fieldOptions.projects[projectId] - ).join(', ')} + + {cell.map( + (projectId) => this.state.data.fieldOptions.projects[projectId] + ).join(', ')} ); if (cell.length === 0) { result = ( - This user has no project affiliations + + {t('This user has no project affiliations', {ns: 'user_accounts'})} + ); } break; - case 'Username': + case t('Username', {ns: 'loris'}): url = loris.BaseURL + '/user_accounts/edit_user/' + row.Username; - result = {cell}; + result = {cell}; break; - case 'Active': - if (row.Active === 'Y') { - result = Yes; - } else if (row.Active === 'N') { - result = No; + case t('Active', {ns: 'loris'}): + const activeKey = t('Active', {ns: 'loris'}); + if (row[activeKey] === 'Y') { + result = {t('Yes', {ns: 'loris'})}; + } else if (row[activeKey] === 'N') { + result = {t('No', {ns: 'loris'})}; } break; - case 'Pending Approval': - if (row['Pending Approval'] === 'Y') { - result = Yes; - } else if (row['Pending Approval'] === 'N') { - result = No; + case t('Pending Approval', {ns: 'user_accounts'}): + const pendingKey = t('Pending Approval', {ns: 'user_accounts'}); + if (row[pendingKey] === 'Y') { + result = {t('Yes', {ns: 'loris'})}; + } else if (row[pendingKey] === 'N') { + result = {t('No', {ns: 'loris'})}; } break; } @@ -126,7 +138,7 @@ class UserAccountsIndex extends Component { * Changes url to be able to add or edit a User. */ addUser() { - location.href='/user_accounts/edit_user/'; + location.href = '/user_accounts/edit_user/'; } /** @@ -135,10 +147,15 @@ class UserAccountsIndex extends Component { * @return {object} */ render() { + const {t} = this.props; // If error occurs, return a message. // XXX: Replace this with a UI component for 500 errors. if (this.state.error) { - return

An error occured while loading the page.

; + return ( +

+ {t('An error occured while loading the page.', {ns: 'loris'})} +

+ ); } // Waiting for async data to load @@ -152,52 +169,87 @@ class UserAccountsIndex extends Component { */ const options = this.state.data.fieldOptions; const fields = [ - {label: 'Site', show: true, filter: { - name: 'site', - type: 'multiselect', - options: options.sites, - }}, - {label: 'Project', show: true, filter: { - name: 'project', - type: 'select', - options: options.projects, - }}, - {label: 'Username', show: true, filter: { - name: 'username', - type: 'text', - }}, - {label: 'Full Name', show: true, filter: { - name: 'fullName', - type: 'text', - }}, - {label: 'Email', show: true, filter: { - name: 'email', - type: 'text', - }}, - {label: 'Active', show: true, filter: { - name: 'active', - type: 'select', - options: options.actives, - }}, - {label: 'Pending Approval', show: true, filter: { - name: 'pendingApproval', - type: 'select', - options: options.pendingApprovals, - }}, - {label: 'Account Request Date', show: true, filter: { - name: 'accountRequestDate', - type: 'date', - hide: true, - }}, + { + label: t('Site', {ns: 'loris'}), + show: true, + filter: { + name: 'site', + type: 'multiselect', + options: options.sites, + }, + }, + { + label: t('Project', {ns: 'loris'}), + show: true, + filter: { + name: 'project', + type: 'select', + options: options.projects, + }, + }, + { + label: t('Username', {ns: 'loris'}), + show: true, + filter: { + name: 'username', + type: 'text', + }, + }, + { + label: t('Full Name', {ns: 'user_accounts'}), + show: true, + filter: { + name: 'fullName', + type: 'text', + }, + }, + { + label: t('Email', {ns: 'loris'}), + show: true, + filter: { + name: 'email', + type: 'text', + }, + }, + { + label: t('Active', {ns: 'loris'}), + show: true, + filter: { + name: 'active', + type: 'select', + options: options.actives, + }, + }, + { + label: t('Pending Approval', {ns: 'user_accounts'}), + show: true, + filter: { + name: 'pendingApproval', + type: 'select', + options: options.pendingApprovals, + }, + }, + { + label: t('Account Request Date', {ns: 'user_accounts'}), + show: true, + filter: { + name: 'accountRequestDate', + type: 'date', + hide: true, + }, + }, ]; const actions = [ - {label: 'Add User', action: this.addUser}, + { + label: t('Add User', {ns: 'user_accounts'}), + action: this.addUser, + }, ]; return ( { i18n.addResourceBundle('ja', 'user_accounts', {}); + i18n.addResourceBundle('hi', 'user_accounts', hiStrings); const Index = withTranslation( ['user_accounts', 'loris'] )(UserAccountsIndex); @@ -226,3 +280,5 @@ window.addEventListener('load', () => { /> ); }); + +export default withTranslation(['user_accounts', 'loris'])(UserAccountsIndex); diff --git a/modules/user_accounts/locale/hi/LC_MESSAGES/user_accounts.po b/modules/user_accounts/locale/hi/LC_MESSAGES/user_accounts.po new file mode 100644 index 00000000000..d9f8aaaa6ac --- /dev/null +++ b/modules/user_accounts/locale/hi/LC_MESSAGES/user_accounts.po @@ -0,0 +1,193 @@ +# Default LORIS strings to be translated (English). +# Copy this to a language specific file and add translations to the +# new file. +# Copyright (C) 2025 +# This file is distributed under the same license as the LORIS package. +# Dave MacFarlane , 2025. +# +msgid "" +msgstr "" +"Project-Id-Version: LORIS 27\n" +"Report-Msgid-Bugs-To: https://github.com/aces/Loris/issues\n" +"POT-Creation-Date: 2025-04-08 14:37-0400\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: hi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "User Accounts" +msgstr "उपयोगकर्ता खाते" + +msgid "Edit User" +msgstr "उपयोगकर्ता संपादित करें" + +msgid "This user has no site affiliations" +msgstr "इस उपयोगकर्ता की कोई साइट संबद्धता नहीं है" + +msgid "This user has no project affiliations" +msgstr "इस उपयोगकर्ता की कोई परियोजना संबद्धता नहीं है" + +msgid "Full Name" +msgstr "पूरा नाम" + +msgid "Pending Approval" +msgstr "स्वीकृति लंबित" + +msgid "Radiologist" +msgstr "रेडियोलॉजिस्ट" + +msgid "Account Request Date" +msgstr "खाता अनुरोध तिथि" + +msgid "Add User" +msgstr "उपयोगकर्ता जोड़ें" + +msgid "The form you submitted contains data entry errors" +msgstr "आपके द्वारा प्रस्तुत फॉर्म में डेटा प्रविष्टि त्रुटियां हैं" + +msgid "Notes" +msgstr "नोट्स" + +msgid "It is recommended to use an email address as the username, for clarity and uniqueness." +msgstr "स्पष्टता और अद्वितीयता के लिए उपयोगकर्ता नाम के रूप में ईमेल पते का उपयोग करने की अनुशंसा की जाती है।" + +msgid "When generating a new password, please notify the user by checking 'Send email to user' box" +msgstr "नया पासवर्ड बनाते समय, कृपया 'उपयोगकर्ता को ईमेल भेजें' बॉक्स को चुनकर उपयोगकर्ता को सूचित करें।" + +msgid "You must leave the password field empty if you want the system to generate one for you" +msgstr "यदि आप चाहते हैं कि सिस्टम आपके लिए पासवर्ड बनाए, तो पासवर्ड फ़ील्ड खाली छोड़ना आवश्यक है।" + +msgid "Add/Edit User" +msgstr "उपयोगकर्ता जोड़ें/संपादित करें" + +msgid "Reject User" +msgstr "उपयोगकर्ता को अस्वीकार करें" + +msgid "Make user name match email address" +msgstr "उपयोगकर्ता नाम को ईमेल पता से मिलाएँ" + +msgid "Generate new password" +msgstr "नया पासवर्ड बनाएं" + +msgid "Degree" +msgstr "डिग्री" + +msgid "Academic Position" +msgstr "शैक्षणिक पद" + +msgid "Institution" +msgstr "संस्थान" + +msgid "Department" +msgstr "विभाग" + +msgid "Street Address" +msgstr "सड़क का पता" + +msgid "City" +msgstr "शहर" + +msgid "State/Province" +msgstr "राज्य/प्रांत" + +msgid "Zip/Postal Code" +msgstr "पिन/डाक कोड" + +msgid "Country" +msgstr "देश" + +msgid "FAX" +msgstr "फैक्स" + +msgid "Send email to user" +msgstr "उपयोगकर्ता को ईमेल भेजें" + +msgid "Confirm Email" +msgstr "ईमेल की पुष्टि करें" + +msgid "Examiner At:" +msgstr "परीक्षक स्थल:" + +msgid "Examiner Status" +msgstr "परीक्षक की स्थिति" + +msgid "Pending approval" +msgstr "अनुमोदन प्रतीक्षारत" + +msgid "Active from" +msgstr "सक्रिय शुरू" + +msgid "Active to" +msgstr "सक्रिय समाप्त" + +msgid "Permissions" +msgstr "अनुमतियाँ" + +msgid "Supervisors" +msgstr "पर्यवेक्षक" + +msgid "You cannot enter a user name if you want it to match the email address" +msgstr "यदि आप उपयोगकर्ता नाम को ईमेल से मेल करना चाहते हैं, तो आप इसे अलग से दर्ज नहीं कर सकते" + +msgid "You must enter a user name or choose to make it match the email address" +msgstr "आपको उपयोगकर्ता नाम दर्ज करना होगा या इसे ईमेल से मेल करने का विकल्प चुनना होगा" + +msgid "The user name already exists" +msgstr "उपयोगकर्ता नाम पहले से मौजूद है" + +msgid "The user name must not exceed 255 characters" +msgstr "उपयोगकर्ता नाम 255 अक्षरों से अधिक नहीं होना चाहिए" + +msgid "You cannot have the user name match an email address that contains a whitespace character" +msgstr "आप उपयोगकर्ता नाम को ऐसे ईमेल से मेल नहीं कर सकते जिसमें रिक्त स्थान हो" + +msgid "Whitespace characters are not allowed in user names" +msgstr "उपयोगकर्ता नाम में रिक्त स्थान की अनुमति नहीं है" + +msgid "Please specify password or click Generate new password" +msgstr "कृपया पासवर्ड निर्दिष्ट करें या 'नया पासवर्ड बनाएं' पर क्लिक करें" + +msgid "Password is required" +msgstr "पासवर्ड आवश्यक है" + +msgid "You must enter an email address" +msgstr "आपको ईमेल पता दर्ज करना होगा" + +msgid "Email and confirmed email do not match" +msgstr "ईमेल और पुष्टि की गई ईमेल मेल नहीं खाते" + +msgid "You must select at least one site/affiliation" +msgstr "आपको कम से कम एक साइट/संलग्नता चुननी होगी" + +msgid "You must select at least one project/affiliation" +msgstr "आपको कम से कम एक प्रोजेक्ट/संलग्नता चुननी होगी" + +msgid "Please specify if examiner is a radiologist" +msgstr "कृपया निर्दिष्ट करें कि परीक्षक रेडियोलॉजिस्ट है या नहीं" + +msgid "Please set pending approval Yes or No" +msgstr "कृपया 'अनुमोदन प्रतीक्षारत' को हाँ या नहीं सेट करें" + +msgid "Please select at least one examiner site or clear the 'Examiner status' fields below (i.e. 'Radiologist' and 'Pending Approval')." +msgstr "कृपया कम से कम एक परीक्षक स्थल चुनें या नीचे के 'परीक्षक स्थिति' फ़ील्ड्स (जैसे 'रेडियोलॉजिस्ट' और 'अनुमोदन प्रतीक्षारत') को साफ़ करें।" + +msgid "Please notice that the \"Active from\" date should be lesser or equal to the \"Active to\" date." +msgstr "कृपया ध्यान दें कि 'सक्रिय शुरू' तिथि, 'सक्रिय समाप्त' तिथि के बराबर या उससे पहले होनी चाहिए।" + +msgid "Your password cannot be your email." +msgstr "आपका पासवर्ड आपका ईमेल नहीं हो सकता।" + +msgid "Your password cannot be your user name." +msgstr "आपका पासवर्ड आपका उपयोगकर्ता नाम नहीं हो सकता।" + +msgid "The passwords do not match." +msgstr "पासवर्ड मेल नहीं खाते।" + +msgid "New and old passwords are identical" +msgstr "नया और पुराना पासवर्ड समान हैं।" + +msgid "This email address is already in use" +msgstr "यह ईमेल पता पहले से उपयोग में है।" diff --git a/modules/user_accounts/locale/user_accounts.pot b/modules/user_accounts/locale/user_accounts.pot index da7b43163f9..e999aa55091 100644 --- a/modules/user_accounts/locale/user_accounts.pot +++ b/modules/user_accounts/locale/user_accounts.pot @@ -24,8 +24,170 @@ msgstr "" msgid "Edit User" msgstr "" -msgid "Pending account approval" +msgid "This user has no site affiliations" msgstr "" -msgid "Pending account approvals" +msgid "This user has no project affiliations" +msgstr "" + +msgid "Full Name" +msgstr "" + +msgid "Pending Approval" +msgstr "" + +msgid "Radiologist" +msgstr "" + +msgid "Account Request Date" +msgstr "" + +msgid "Add User" +msgstr "" + +msgid "The form you submitted contains data entry errors" +msgstr "" + +msgid "Notes" +msgstr "" + +msgid "It is recommended to use an email address as the username, for clarity and uniqueness." +msgstr "" + +msgid "When generating a new password, please notify the user by checking 'Send email to user' box" +msgstr "" + +msgid "You must leave the password field empty if you want the system to generate one for you" +msgstr "" + +msgid "Add/Edit User" +msgstr "" + +msgid "Reject User" +msgstr "" + +msgid "Make user name match email address" +msgstr "" + +msgid "Generate new password" +msgstr "" + +msgid "Degree" +msgstr "" + +msgid "Academic Position" +msgstr "" + +msgid "Institution" +msgstr "" + +msgid "Department" +msgstr "" + +msgid "Street Address" +msgstr "" + +msgid "City" +msgstr "" + +msgid "State/Province" +msgstr "" + +msgid "Zip/Postal Code" +msgstr "" + +msgid "Country" +msgstr "" + +msgid "FAX" +msgstr "" + +msgid "Send email to user" +msgstr "" + +msgid "Confirm Email" +msgstr "" + +msgid "Examiner At:" +msgstr "" + +msgid "Examiner Status" +msgstr "" + +msgid "Pending approval" +msgstr "" + +msgid "Active from" +msgstr "" + +msgid "Active to" +msgstr "" + +msgid "Permissions" +msgstr "" + +msgid "Supervisors" +msgstr "" + +msgid "You cannot enter a user name if you want it to match the email address" +msgstr "" + +msgid "You must enter a user name or choose to make it match the email address" +msgstr "" + +msgid "The user name already exists" +msgstr "" + +msgid "The user name must not exceed 255 characters" +msgstr "" + +msgid "You cannot have the user name match an email address that contains a whitespace character" +msgstr "" + +msgid "Whitespace characters are not allowed in user names" +msgstr "" + +msgid "Please specify password or click Generate new password" +msgstr "" + +msgid "Password is required" +msgstr "" + +msgid "You must enter an email address" +msgstr "" + +msgid "Email and confirmed email do not match" +msgstr "" + +msgid "You must select at least one site/affiliation" +msgstr "" + +msgid "You must select at least one project/affiliation" +msgstr "" + +msgid "Please specify if examiner is a radiologist" +msgstr "" + +msgid "Please set pending approval Yes or No" +msgstr "" + +msgid "Please select at least one examiner site or clear the 'Examiner status' fields below (i.e. 'Radiologist' and 'Pending Approval')." +msgstr "" + +msgid "Please notice that the \"Active from\" date should be lesser or equal to the \"Active to\" date." +msgstr "" + +msgid "Your password cannot be your email." +msgstr "" + +msgid "Your password cannot be your user name." +msgstr "" + +msgid "The passwords do not match." +msgstr "" + +msgid "New and old passwords are identical" +msgstr "" + +msgid "This email address is already in use" msgstr "" diff --git a/modules/user_accounts/php/edit_user.class.inc b/modules/user_accounts/php/edit_user.class.inc index 3c9450b7677..f3ae4d5d625 100644 --- a/modules/user_accounts/php/edit_user.class.inc +++ b/modules/user_accounts/php/edit_user.class.inc @@ -11,9 +11,10 @@ * @license http://www.gnu.org/licenses/gpl-3.0.txt GPLv3 * @link https://www.github.com/aces/Loris/ */ + namespace LORIS\user_accounts; -use \Psr\Http\Message\ServerRequestInterface; -use \Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Message\ResponseInterface; /** * Implements the user account page @@ -55,7 +56,7 @@ class Edit_User extends \NDB_Form * * @return bool true if user has access, false otherwise. */ - function _hasAccess(\User $editor) : bool + function _hasAccess(\User $editor): bool { if ($editor->hasPermission('user_accounts_multisite')) { return true; @@ -127,15 +128,15 @@ class Edit_User extends \NDB_Form } $defaults['examiner'] = $defaults['examiner'] ?? []; - foreach ($defaults['examiner'] as $cid=>$vals) { + foreach ($defaults['examiner'] as $cid => $vals) { //sets pending approval info - if ($cid=='pending') { + if ($cid == 'pending') { $defaults['examiner_pending'] = $vals; continue; } //gets radiologist Y/N from any of the active sites - if ($vals[0]=='Y') { - if ($vals[1]==='1') { + if ($vals[0] == 'Y') { + if ($vals[1] === '1') { $defaults['examiner_radiologist'] = 'Y'; } else { $defaults['examiner_radiologist'] = 'N'; @@ -151,13 +152,13 @@ class Edit_User extends \NDB_Form $curr_sub = \NDB_Notifier::getUserNotificationModuleServices( $user_id ); - foreach ($curr_sub as $module=>$operations) { + foreach ($curr_sub as $module => $operations) { foreach ($operations as $operation => $services) { unset($services['desc']); foreach ($services as $service => $subscribed) { $var_name = "notif_".$module."_".$operation."_".$service; - if ($subscribed==='Y') { + if ($subscribed === 'Y') { $defaults[$var_name] = 'on'; } } @@ -529,7 +530,6 @@ class Edit_User extends \NDB_Form // Now set the password. Note that this field is named incorrectly // and represents a plaintext password, not a hash. if (isset($values['Password_hash'])) { - $user->updatePassword( new \Password( htmlspecialchars_decode($values['Password_hash']) @@ -638,7 +638,7 @@ class Edit_User extends \NDB_Form * * @return ResponseInterface The outgoing PSR15 response */ - public function handle(ServerRequestInterface $request) : ResponseInterface + public function handle(ServerRequestInterface $request): ResponseInterface { $matches = []; preg_match('#.*/edit_user/(.*)#', $request->getUri()->getPath(), $matches); @@ -677,20 +677,28 @@ class Edit_User extends \NDB_Form // it is a new user if ($this->identifier == '') { // user name - $this->addBasicText('UserID', 'User name', ['required' => true]); + $this->addBasicText( + 'UserID', + dgettext( + "loris", + "Username" + ), + ['required' => true] + ); $this->addCheckbox( 'NA_UserID', - 'Make user name match email address', + dgettext("user_accounts", "Make user name match email address"), [] ); - } else { // It is an existing user: // display user name and account request date - $this->addScoreColumn('UserID', 'User name'); + $this->addScoreColumn('UserID', dgettext("loris", "Username")); } - // Account Request Date - always displayed - $this->addScoreColumn('account_request_date', 'Account Request Date'); + $this->addScoreColumn( + 'account_request_date', + dgettext("user_accounts", "Account Request Date") + ); // password if ($this->isCreatingNewUser()) { @@ -699,20 +707,36 @@ class Edit_User extends \NDB_Form $pwd_attribs = []; } - $this->addPassword('Password_hash', 'Password', $pwd_attribs); - $this->addCheckbox('NA_Password', 'Generate new password', []); - $this->addPassword('__Confirm', 'Confirm Password', $pwd_attribs); + $this->addPassword( + 'Password_hash', + dgettext("loris", "Password"), + $pwd_attribs + ); + $this->addCheckbox( + 'NA_Password', + dgettext("user_accounts", "Generate new password"), + [] + ); + $this->addPassword( + '__Confirm', + dgettext("loris", "Confirm Password"), + $pwd_attribs + ); // The supplied pattern is: // - must have at least one non-whitespace characters // - once leading and trailing spaces are stripped, the field should // not exceed 120 chars $onInvalidMsg - = "this.setCustomValidity('First name is required and " - . "should not exceed 120 characters')"; + = "this.setCustomValidity('" + . dgettext( + "user_accounts", + "First name is required and should not exceed 120 characters" + ) + . "')"; $this->addBasicText( 'First_name', - 'First name', + dgettext("loris", "First name"), [], [ 'oninvalid' => $onInvalidMsg, @@ -726,11 +750,15 @@ class Edit_User extends \NDB_Form // - once leading and trailing spaces are stripped, the field should // not exceed 120 chars $onInvalidMsg - = "this.setCustomValidity('Last name is required and " - . "should not exceed 120 characters')"; + = "this.setCustomValidity('" + . dgettext( + "user_accounts", + "Last name is required and should not exceed 120 characters" + ) + . "')"; $this->addBasicText( 'Last_name', - 'Last name', + dgettext("loris", "Last name"), [], [ 'oninvalid' => $onInvalidMsg, @@ -745,28 +773,66 @@ class Edit_User extends \NDB_Form // if the option is not set or if it's and it's true then display it if ($additional_user_info) { - $this->addBasicText('Degree', 'Degree'); - $this->addBasicText('Position_title', 'Academic Position'); - $this->addBasicText('Institution', 'Institution'); - $this->addBasicText('Department', 'Department'); - $this->addBasicText('Address', 'Street Address'); - $this->addBasicText('City', 'City'); - $this->addBasicText('State', 'State/Province'); - $this->addBasicText('Zip_code', 'Zip/Postal Code'); - $this->addBasicText('Country', 'Country'); - $this->addBasicText('Fax', 'FAX'); + $this->addBasicText( + 'Degree', + dgettext("user_accounts", "Degree") + ); + $this->addBasicText( + 'Position_title', + dgettext("user_accounts", "Academic Position") + ); + $this->addBasicText( + 'Institution', + dgettext("user_accounts", "Institution") + ); + $this->addBasicText( + 'Department', + dgettext("user_accounts", "Department") + ); + $this->addBasicText( + 'Address', + dgettext("user_accounts", "Street Address") + ); + $this->addBasicText( + 'City', + dgettext("user_accounts", "City") + ); + $this->addBasicText( + 'State', + dgettext("user_accounts", "State/Province") + ); + $this->addBasicText( + 'Zip_code', + dgettext("user_accounts", "Zip/Postal Code") + ); + $this->addBasicText( + 'Country', + dgettext("user_accounts", "Country") + ); + $this->addBasicText( + 'Fax', + dgettext("user_accounts", "FAX") + ); } // email address - $this->addBasicText('Email', 'Email address', ['required' => true]); - $this->addCheckbox('SendEmail', 'Send email to user', []); + $this->addBasicText( + 'Email', + dgettext("loris", "Email address"), + ['required' => true] + ); + $this->addCheckbox( + 'SendEmail', + dgettext("user_accounts", "Send email to user"), + [] + ); // Add a confirm email text field only if creating a new user // (to make sure that account creation email goes through) if ($this->isCreatingNewUser()) { $this->addBasicText( '__ConfirmEmail', - 'Confirm Email', + dgettext("user_accounts", "Confirm Email"), [], ['required' => true] ); @@ -795,7 +861,7 @@ class Edit_User extends \NDB_Form $this->addSelect( 'CenterIDs', - 'Sites', + dgettext("loris", "Sites"), $siteOptions, [ 'class' => 'form-control input-sm resizable', @@ -815,7 +881,7 @@ class Edit_User extends \NDB_Form $this->addSelect( 'ProjectIDs', - 'Projects', + dgettext("loris", "Projects"), $projectOptions, [ 'class' => 'form-control input-sm resizable', @@ -830,7 +896,7 @@ class Edit_User extends \NDB_Form $this->addSelect( "examiner_sites", - "Examiner at:", + dgettext("user_accounts", "Examiner At:"), $siteOptions, [ 'class' => 'form-control input-sm resizable', @@ -842,30 +908,30 @@ class Edit_User extends \NDB_Form ); $examinerGroup[] = $this->createSelect( "examiner_radiologist", - "Radiologist: ", + dgettext("user_accounts", "Radiologist") . ": ", [ '' => "", - 'Y' => 'Yes', - 'N' => 'No', + 'Y' => dgettext("loris", "Yes"), + 'N' => dgettext("loris", "No"), ] ); $examinerGroup[] = $this->createLabel( - "Pending Approval:" + dgettext("user_accounts", "Pending Approval") . ":" ); $examinerGroup[] = $this->createSelect( "examiner_pending", - "Pending Approval: ", + dgettext("user_accounts", "Pending Approval") . ": ", [ - '' => "", - 'Y' => 'Yes', - 'N' => 'No', + '' => dgettext("loris", "None"), + 'Y' => dgettext("loris", "Yes"), + 'N' => dgettext("loris", "No"), ] ); $this->addGroup( $examinerGroup, "examiner_group", - "Examiner Status", + dgettext("user_accounts", "Examiner Status"), $this->_GUIDelimiter ); unset($examinerGroup); @@ -877,19 +943,19 @@ class Edit_User extends \NDB_Form if (!$this->_isEditingOwnAccount()) { $this->addSelect( "Pending_approval", - "Pending approval", + dgettext("user_accounts", "Pending approval"), [ - 'Y' => 'Yes', - 'N' => 'No', + 'Y' => dgettext("loris", "Yes"), + 'N' => dgettext("loris", "No"), ] ); $this->addSelect( 'Active', - 'Active', + dgettext("loris", "Active"), [ - 'Y' => 'Yes', - 'N' => 'No' + 'Y' => dgettext("loris", "Yes"), + 'N' => dgettext("loris", "No") ] ); @@ -903,14 +969,14 @@ class Edit_User extends \NDB_Form $this->addBasicDate( 'active_from', - 'Active from', + dgettext("user_accounts", "Active from"), $dateOptions, $dateAttributes ); $this->addBasicDate( 'active_to', - 'Active to', + dgettext("user_accounts", "Active to"), $dateOptions, $dateAttributes ); @@ -942,7 +1008,7 @@ class Edit_User extends \NDB_Form . "

" - .ucwords($row['type']) + . ucwords($row['type']) . '

' . "
" ); @@ -956,7 +1022,7 @@ class Edit_User extends \NDB_Form $attribs['disabled'] = true; } $group[] = $this->createCheckbox( - 'permID['.$row['permID'].']', + 'permID[' . $row['permID'] . ']', htmlspecialchars( $row['label'], ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML5, @@ -967,7 +1033,12 @@ class Edit_User extends \NDB_Form $attribs ); } - $this->addGroup($group, 'PermID_Group', 'Permissions', ""); + $this->addGroup( + $group, + 'PermID_Group', + dgettext("user_accounts", "Permissions"), + "" + ); unset($group); //getting users name and emails to create checkboxes @@ -988,14 +1059,14 @@ class Edit_User extends \NDB_Form '
' . "

" - . "Data Supervisors to Email

" + . dgettext('loris', 'Data Supervisors to Email') . " " . "
" ); $attribs = $this->_isEditingOwnAccount() ? ['disabled' => true] : null; foreach ($results as $row) { $group[] = $this->createCheckbox( - 'supervisorEmail[' . $row['email'] .']', + 'supervisorEmail[' . $row['email'] . ']', htmlspecialchars( $row['Real_Name'], ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML5, @@ -1007,7 +1078,12 @@ class Edit_User extends \NDB_Form ); } - $this->addGroup($group, 'Supervisors_Group', 'Supervisors', ""); + $this->addGroup( + $group, + 'Supervisors_Group', + dgettext("user_accounts", "Supervisors"), + "" + ); unset($group); if (!$this->isCreatingNewUser()) { @@ -1072,13 +1148,19 @@ class Edit_User extends \NDB_Form // Clicked on "UID == email" and specified a UID if (!empty($values['UserID']) && $values['NA_UserID'] == 'on') { $errors['UserID_Group'] - = 'You cannot enter a user name ' - . 'if you want it to match the email address'; + = dgettext( + "user_accounts", + 'You cannot enter a user name ' + . 'if you want it to match the email address' + ); } elseif (empty($values['UserID']) && $values['NA_UserID'] != 'on') { // Not clicked on "UID == email" and not specified a UID $errors['UserID_Group'] - = 'You must enter a user name ' - . 'or choose to make it match the email address'; + = dgettext( + "user_accounts", + 'You must enter a user name ' + . 'or choose to make it match the email address' + ); } elseif (!empty($values['UserID']) || ($values['NA_UserID'] == 'on' && $values['Email']) ) { @@ -1096,24 +1178,33 @@ class Edit_User extends \NDB_Form ); if ($result > 0) { - $errors['UserID_Group'] = 'The user name already exists'; + $errors['UserID_Group'] = dgettext( + "user_accounts", + "The user name already exists" + ); } if (strlen($effectiveUID) > 255) { - $errors['UserID_Group'] - = 'The user name must not exceed 255 characters'; + $errors['UserID_Group'] = dgettext( + "user_accounts", + "The user name must not exceed 255 characters" + ); } // Check that user name does not contain a whitespace character if (preg_match('/\s/', $effectiveUID)) { // Note: email addresses can contain comments which themselves // can contain spaces if ($values['NA_UserID'] == 'on') { - $errors['UserID_Group'] - = 'You cannot have the user name match an email address' - . ' that contains a whitespace character'; + $errors['UserID_Group'] = dgettext( + "user_accounts", + "You cannot have the user name match an email address" + . " that contains a whitespace character" + ); } else { - $errors['UserID_Group'] - = 'Whitespace characters are not allowed in user names'; + $errors['UserID_Group'] = dgettext( + "user_accounts", + "Whitespace characters are not allowed in user names" + ); } } } @@ -1130,7 +1221,10 @@ class Edit_User extends \NDB_Form if ($values['Email'] === $values['Password_hash'] && $values['Password_hash'] !== '' ) { - $errors['Password'] = self::PASSWORD_ERROR_IS_EMAIL; + $errors['Password'] = dgettext( + "user_accounts", + "Your password cannot be your email." + ); } // Make sure the user is not using their username as their password. @@ -1143,7 +1237,10 @@ class Edit_User extends \NDB_Form || (!empty($this->identifier) && $this->identifier === ($values['Password_hash'] ?? '')) ) { - $errors['Password'] = self::PASSWORD_ERROR_IS_USER; + $errors['Password'] = dgettext( + "user_accounts", + "Your password cannot be your user name." + ); } if (!is_null($this->identifier)) { @@ -1160,14 +1257,19 @@ class Edit_User extends \NDB_Form && empty($values['Password_hash']) && $values['NA_Password'] != 'on' ) { - $errors['Password'] - = 'Please specify password or click Generate new password'; + $errors['Password'] = dgettext( + "user_accounts", + "Please specify password or click Generate new password" + ); } } // Ensure that the password and confirm password fields match. // TODO This validation should be done on the front-end instead. if ($plaintext !== $values['__Confirm']) { - $errors['Password'] = self::PASSWORD_ERROR_NO_MATCH; + $errors['Password'] = dgettext( + "user_accounts", + "The passwords do not match." + ); } // if password is user-defined, and user wants to change password @@ -1183,7 +1285,10 @@ class Edit_User extends \NDB_Form $isPasswordDifferent = \User::factory($this->identifier) ->isPasswordDifferent($decoded); if (! $isPasswordDifferent) { - $errors['Password'] = self::PASSWORD_ERROR_NO_CHANGE; + $errors['Password'] = dgettext( + "user_accounts", + "New and old passwords are identical" + ); } } catch (\InvalidArgumentException $e) { $errors['Password'] = $e->getMessage(); @@ -1195,24 +1300,29 @@ class Edit_User extends \NDB_Form && $values['NA_Password'] == "on" && $values['SendEmail'] != "on" ) { - $errors['Email'] - = 'When generating a new password, ' - . 'please notify the user by checking Send email to user box'; + $errors['Email'] = dgettext( + "user_accounts", + "When generating a new password, please notify the user by checking" + . " 'Send email to user' box" + ); } if (isset($values['NA_Password']) && $values['NA_Password'] == 'on' && $plaintext != '' ) { - $errors['Password'] = 'You must leave the password field empty ' - . 'if you want the system to generate one for you'; + $errors['Password'] = dgettext( + "user_accounts", + "You must leave the password field empty if you want the system to" + . " generate one for you" + ); } if (is_null($this->identifier) && (!isset($values['NA_Password']) || $values['NA_Password'] != 'on') && empty($plaintext) ) { - $errors['Password'] = 'Password is required'; + $errors['Password'] = dgettext("user_accounts", "Password is required"); } //====================================== @@ -1226,13 +1336,18 @@ class Edit_User extends \NDB_Form $errors['Email'] = $emailError; } elseif ($this->isCreatingNewUser()) { if ($values['Email'] != $values['__ConfirmEmail']) { - $errors['__ConfirmEmail'] = 'Email and confirmed email ' - . ' do not match'; + $errors['__ConfirmEmail'] = dgettext( + "user_accounts", + "Email and confirmed email do not match" + ); } } } else { // No email entered: error - $errors['Email'] = 'You must enter an email address'; + $errors['Email'] = dgettext( + "user_accounts", + "You must enter an email address" + ); } //====================================== @@ -1240,8 +1355,10 @@ class Edit_User extends \NDB_Form //====================================== // Ensure that at least one site is selected if (empty($values['CenterIDs'])) { - $errors['sites_group'] = "You must select at least one " . - "site/affiliation"; + $errors['sites_group'] = dgettext( + "user_accounts", + "You must select at least one site/affiliation" + ); } //====================================== @@ -1249,8 +1366,10 @@ class Edit_User extends \NDB_Form //====================================== // Ensure that at least one site is selected if (empty($values['ProjectIDs'])) { - $errors['projects_group'] = "You must select at least one " . - "project/affiliation"; + $errors['projects_group'] = dgettext( + "user_accounts", + "You must select at least one project/affiliation" + ); } //====================================== @@ -1259,22 +1378,28 @@ class Edit_User extends \NDB_Form if ($editor->hasPermission('examiner_multisite')) { if ($values['examiner_sites'] ?? null) { if ($values['examiner_radiologist'] == '') { - $errors['examiner_group'] = "Please specify if examiner " . - "is a radiologist"; - + $errors['examiner_group'] = dgettext( + "user_accounts", + "Please specify if examiner is a radiologist" + ); } if ($values['examiner_radiologist'] !== '' && $values['examiner_pending'] == '' ) { - $errors['examiner_group'] = "Please set pending " . - "approval Yes or No"; + $errors['examiner_group'] = dgettext( + "user_accounts", + "Please set pending approval Yes or No" + ); } } elseif ($values['examiner_radiologist'] !== '' || $values['examiner_pending'] ?? '' !== '' ) { - $errors['examiner_sites'] = "Please select at least one examiner - site or clear the 'Examiner status' fields below (i.e. - 'Radiologist' and 'Pending Approval')."; + $errors['examiner_sites'] = dgettext( + "user_accounts", + "Please select at least one examiner site or clear the " + . "'Examiner status' fields below " + . "(i.e. 'Radiologist' and 'Pending Approval')." + ); } } @@ -1289,9 +1414,11 @@ class Edit_User extends \NDB_Form if (($values['active_to'] != null) && ($values['active_from'] > $values['active_to']) ) { - $errors['active_timeWindows'] - = 'Please notice that the "Active from" - date should be lesser or equal to the "Active to" date.'; + $errors['active_timeWindows'] = dgettext( + "user_accounts", + "Please notice that the \"Active from\" date should be" + . " lesser or equal to the \"Active to\" date." + ); } return $errors; } @@ -1311,11 +1438,14 @@ class Edit_User extends \NDB_Form // Although some of these characters are legal in emails, due to the // current HTML escaping method, it is better to reject email // addresses containing them - return 'Email address can not contain any the following '. - 'characters: <, >, & and "'; + return dgettext( + 'loris', + 'Email address cannot contain any of the following characters: ' + . '<, >, &, and "' + ); } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) { // If email not syntactically valid - return "Invalid email address"; + return dgettext('loris', 'Invalid email address'); } // check email address' uniqueness @@ -1329,7 +1459,10 @@ class Edit_User extends \NDB_Form // Email already exists in database if ($result > 0) { - return self::EMAIL_NOT_UNIQUE; + return dgettext( + "user_accounts", + "This email address is already in use" + ); } return null; diff --git a/modules/user_accounts/php/user_accounts.class.inc b/modules/user_accounts/php/user_accounts.class.inc index e12c6ac9722..e2abf3de32d 100644 --- a/modules/user_accounts/php/user_accounts.class.inc +++ b/modules/user_accounts/php/user_accounts.class.inc @@ -11,6 +11,7 @@ * @license Loris license * @link https://www.github.com/aces/Loris/ */ + namespace LORIS\user_accounts; /** @@ -40,7 +41,7 @@ class User_Accounts extends \DataFrameworkMenu * * @return boolean */ - function _hasAccess(\User $user) : bool + function _hasAccess(\User $user): bool { return $user->hasAnyPermission(self::PERMISSIONS); } @@ -51,7 +52,7 @@ class User_Accounts extends \DataFrameworkMenu * * @return ?array of permissions or null */ - public function allSitePermissionNames() : ?array + public function allSitePermissionNames(): ?array { return ['user_accounts_multisite']; } @@ -62,7 +63,7 @@ class User_Accounts extends \DataFrameworkMenu * * @return bool true */ - public function useProjectFilter() : bool + public function useProjectFilter(): bool { return true; } @@ -72,11 +73,11 @@ class User_Accounts extends \DataFrameworkMenu * * @return array */ - protected function getFieldOptions() : array + protected function getFieldOptions(): array { $yesNoOptions = [ - 'Y' => 'Yes', - 'N' => 'No', + 'Y' => dgettext("loris", "Yes"), + 'N' => dgettext("loris", "No"), ]; return [ @@ -92,7 +93,7 @@ class User_Accounts extends \DataFrameworkMenu * * @return \Loris\Data\Provisioner */ - public function getBaseDataProvisioner() : \LORIS\Data\Provisioner + public function getBaseDataProvisioner(): \LORIS\Data\Provisioner { return new UserAccountRowProvisioner($this->loris); } @@ -113,4 +114,3 @@ class User_Accounts extends \DataFrameworkMenu ); } } - diff --git a/modules/user_accounts/templates/form_edit_user.tpl b/modules/user_accounts/templates/form_edit_user.tpl index 74f97a53ff3..1040474b460 100644 --- a/modules/user_accounts/templates/form_edit_user.tpl +++ b/modules/user_accounts/templates/form_edit_user.tpl @@ -2,28 +2,28 @@
{if $form.errors} {/if}
-

Password Rules

+

{dgettext("loris", "Password Rules")}

    -
  • The password must be at least 8 characters long.
  • -
  • The password cannot be your username or email address.
  • -
  • No special characters are required but your password must be sufficiently complex to be accepted.
  • +
  • {dgettext("loris", "The password must be at least 8 characters long.")}
  • +
  • {dgettext("loris", "The password cannot be your username or email address.")}
  • +
  • {dgettext("loris", "No special characters are required but your password must be sufficiently complex to be accepted.")}
-

Please choose a unique password.

-

We suggest using a password manager to generate one for you.

-

Notes

+

{dgettext("loris", "Please choose a unique password.")}

+

{dgettext("loris", "We suggest using a password manager to generate one for you.")}

+

{dgettext("user_accounts", "Notes")}

    -
  • It is recommended to use an email address as the username, for clarity and uniqueness.
  • -
  • When generating a new password, please notify the user by checking 'Send email to user' box below!
  • +
  • {dgettext("user_accounts", "It is recommended to use an email address as the username, for clarity and uniqueness.")}
  • +
  • {dgettext("user_accounts", "When generating a new password, please notify the user by checking 'Send email to user' box below!")}
-

Add/Edit User

+

{dgettext("user_accounts", "Add/Edit User")}

{if $form.errors.UserID_Group|default}
{else} @@ -453,7 +453,7 @@ {$form.account_request_date.label}
- {$form.account_request_date.html|default:'None'} + {$form.account_request_date.html|default:dgettext('loris', 'None')}
@@ -496,19 +496,19 @@
- +
- +
- +
{if $can_reject}
- +
{/if}