Skip to content

Commit 22d32b6

Browse files
authored
[dashboard/multilingual] Add multilingual config settings (#9994)
This adds the backend infrastructure to allow multilingual config settings with different values per language, so that pages such as the project description on the dashboard can be localized. ConfigSetting now has a "Multilingual" boolean flag to determine if the config setting should be localizable. If it is multilingual, a new `getMultilingualSetting` method on the NDB_Config object can be used to get the value for a particular language code. Translated strings are stored in a new "ConfigI18n" table (the casing follows the standard of the Config tables, not the language table for internal consistency.) When a translated version does not exist, the `getMultilingualSetting` function will fall back to the non-localized getSetting value. There is not currently a frontend infrastructure to populate ConfigI18n. The values must be done on the backend.
1 parent 00193bb commit 22d32b6

File tree

8 files changed

+241
-126
lines changed

8 files changed

+241
-126
lines changed

SQL/0000-00-03-ConfigTables.sql

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,21 @@ CREATE TABLE `ConfigSettings` (
1212
`Parent` int(11) DEFAULT NULL,
1313
`Label` varchar(255) DEFAULT NULL,
1414
`OrderNumber` int(11) DEFAULT NULL,
15+
`Multilingual` boolean DEFAULT false,
1516
PRIMARY KEY (`ID`),
1617
UNIQUE KEY `Name` (`Name`)
1718
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
1819

20+
CREATE TABLE `ConfigI18n` (
21+
`Value` text NOT NULL,
22+
`ConfigID` int(11) DEFAULT NULL,
23+
`LanguageID` int(10) unsigned DEFAULT NULL,
24+
KEY `ConfigID` (`ConfigID`),
25+
KEY `LanguageID` (`LanguageID`),
26+
CONSTRAINT `ConfigI18n_ibfk_1` FOREIGN KEY (`ConfigID`) REFERENCES `ConfigSettings` (`ID`),
27+
CONSTRAINT `ConfigI18n_ibfk_2` FOREIGN KEY (`LanguageID`) REFERENCES `language` (`language_id`)
28+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
29+
1930

2031
CREATE TABLE `Config` (
2132
`ID` int(11) NOT NULL AUTO_INCREMENT,
@@ -88,7 +99,7 @@ INSERT INTO ConfigSettings (Name, Description, Visible, AllowMultiple, DataType,
8899

89100

90101
INSERT INTO ConfigSettings (Name, Description, Visible, AllowMultiple, Label, OrderNumber) VALUES ('dashboard', 'Settings that affect the appearance of the dashboard and its charts', 1, 0, 'Dashboard', 5);
91-
INSERT INTO ConfigSettings (Name, Description, Visible, AllowMultiple, DataType, Parent, Label, OrderNumber) SELECT 'projectDescription', 'Description of the study displayed in main dashboard panel', 1, 0, 'textarea', ID, 'Project Description', 1 FROM ConfigSettings WHERE Name="dashboard";
102+
INSERT INTO ConfigSettings (Name, Description, Visible, AllowMultiple, DataType, Parent, Label, OrderNumber, Multilingual) SELECT 'projectDescription', 'Description of the study displayed in main dashboard panel', 1, 0, 'textarea', ID, 'Project Description', 1, true FROM ConfigSettings WHERE Name="dashboard";
92103
INSERT INTO ConfigSettings (Name, Description, Visible, AllowMultiple, DataType, Parent, Label, OrderNumber) SELECT 'recruitmentTarget', 'Target number of participants for the study', 1, 0, 'text', ID, 'Target number of participants', 2 FROM ConfigSettings WHERE Name="dashboard";
93104

94105
INSERT INTO ConfigSettings (Name, Description, Visible, AllowMultiple, Label, OrderNumber) VALUES ('imaging_modules', 'DICOM Archive and Imaging Browser settings', 1, 0, 'Imaging Modules', 6);
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
ALTER table ConfigSettings ADD COLUMN Multilingual boolean DEFAULT false;
2+
UPDATE ConfigSettings SET Multilingual=true WHERE Name='projectDescription';
3+
4+
CREATE TABLE `ConfigI18n` (
5+
`Value` text NOT NULL,
6+
`ConfigID` int(11) DEFAULT NULL,
7+
`LanguageID` int(10) unsigned DEFAULT NULL,
8+
KEY `ConfigID` (`ConfigID`),
9+
KEY `LanguageID` (`LanguageID`),
10+
CONSTRAINT `ConfigI18n_ibfk_1` FOREIGN KEY (`ConfigID`) REFERENCES `ConfigSettings` (`ID`),
11+
CONSTRAINT `ConfigI18n_ibfk_2` FOREIGN KEY (`LanguageID`) REFERENCES `language` (`language_id`)
12+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
13+
14+
-- Sample translation of projectDescription for testing. We do not have a
15+
-- foreign key value in the 'language' table to add it to RB.
16+
-- INSERT INTO ConfigI18n VALUES ('このデータベースは、様々な場所で収集された画像データと行動データの両方をオンラインで保存するための仕組みを提供します。このフレームワークには、このプロセスを可能な限り効率的かつシンプルにするためのツールがいくつか用意されています。データベースに関する詳細な情報については、右上のヘルプアイコンをクリックしてください。それ以外の場合は、DCCまでお気軽にお問い合わせください。私たちは、データ収集を楽しいものにすることを目指しています。', 48, 2)

modules/dashboard/php/projectdescription.class.inc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ class ProjectDescription extends \LORIS\Http\Endpoint
2121
*/
2222
public function handle(ServerRequestInterface $request) : ResponseInterface
2323
{
24-
$desc = $this->loris->getConfiguration()->getSetting('projectDescription');
24+
$settings = \NDB_Factory::singleton()->settings();
25+
$desc = $settings->projectDescription($request->getAttribute("user"));
2526
return new \LORIS\Http\Response\JSON\OK(['Description' => $desc]);
2627
}
2728

php/libraries/NDB_Config.class.inc

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,69 @@ class NDB_Config
434434

435435
}
436436

437+
/**
438+
* Gets a config setting which may have variations in different languages.
439+
*
440+
* Translated strings have some restrictions that do not apply to
441+
* getConfig()
442+
*
443+
* 1. The config name must be a direct setting and not a hierarchical one
444+
* 2. The return type must be a string (otherwise what are you translating?)
445+
* 3. The value must come from the database, and not config.xml
446+
*
447+
* If a config setting value does not exist in a localized format for
448+
* $langcode, this function will fall back on the "default" (generally
449+
* English) getSetting() value for $name.
450+
*
451+
* @param string $langcode The language of the setting to retrieve
452+
* @param string $name The config setting name
453+
*
454+
* @return string
455+
*/
456+
function getMultilingualSetting(string $langcode, string $name): string
457+
{
458+
if (isset($this->settingCache[$name][$langcode])) {
459+
return $this->settingCache[$name][$langcode];
460+
}
461+
462+
$factory = NDB_Factory::singleton();
463+
464+
$db = $factory->database();
465+
// Verify that it's really a multilingual setting.
466+
$configSetting = $db->pselect(
467+
"SELECT ID, AllowMultiple
468+
FROM ConfigSettings cs
469+
WHERE cs.Name=:nm AND Multilingual=true",
470+
["nm" => $name]
471+
);
472+
473+
if (count($configSetting) !== 1) {
474+
throw new ConfigurationException(
475+
"Config setting $name does not exist in database "
476+
. "as a multilingual setting"
477+
);
478+
}
479+
480+
$localizedVal = $db->pselectOne(
481+
"SELECT Value FROM ConfigI18n i18n
482+
JOIN language l ON (l.language_id=i18n.LanguageID)
483+
WHERE l.language_code=:lc AND i18n.ConfigID=:cid",
484+
[
485+
'lc' => $langcode,
486+
'cid' => $configSetting->getFirstRow()['ID'],
487+
]
488+
);
489+
490+
if ($localizedVal !== null) {
491+
$this->settingCache[$name] = [$langcode => $localizedVal];
492+
return $localizedVal;
493+
}
494+
495+
// Fallback on the unlocalized setting value.
496+
$this->settingCache[$name] = [$langcode => $this->getSetting($name)];
497+
return $this->settingCache[$name][$langcode];
498+
}
499+
437500
/**
438501
* Helper function to determine whether a setting with a boolean value is
439502
* enabled, i.e. equal to "true".

php/libraries/Settings.class.inc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,22 @@ class Settings
8181
return $this->_getBooleanSetting('sandbox');
8282
}
8383

84+
/**
85+
* Get the project description which is displayed on the dashboard
86+
* for a user.
87+
*
88+
* @param \User $user The user seeing the description.
89+
*
90+
* @return string
91+
*/
92+
public function projectDescription(\User $user): string
93+
{
94+
return $this->_config->getMultilingualSetting(
95+
$user->getLanguageCode(),
96+
"projectDescription"
97+
);
98+
}
99+
84100
/**
85101
* Get database name from config
86102
*

raisinbread/RB_files/RB_Config.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/*M!999999\- enable the sandbox mode */
12
SET FOREIGN_KEY_CHECKS=0;
23
TRUNCATE TABLE `Config`;
34
LOCK TABLES `Config` WRITE;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/*M!999999\- enable the sandbox mode */
2+
SET FOREIGN_KEY_CHECKS=0;
3+
TRUNCATE TABLE `ConfigI18n`;
4+
LOCK TABLES `ConfigI18n` WRITE;
5+
UNLOCK TABLES;
6+
SET FOREIGN_KEY_CHECKS=1;

0 commit comments

Comments
 (0)