+
+
+
+ HTML;
+ $response = $DIC->http()->response()->withBody(ILIAS\Filesystem\Stream\Streams::ofString($html));
+ $DIC->http()->saveResponse($response);
+ $DIC->http()->sendResponse();
+ $DIC->http()->close();
+
+ }
+
/**
* @throws ilMDServicesException
*/
diff --git a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerAccessToken.php b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerAccessToken.php
new file mode 100644
index 000000000000..0d215d1dc50d
--- /dev/null
+++ b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerAccessToken.php
@@ -0,0 +1,49 @@
+ $scopes */
+ private function __construct(
+ private readonly string $client_id,
+ private readonly array $scopes
+ ) {
+ }
+
+ public static function fromVerifiedToken(object $token): ?self
+ {
+ $client_id = $token->sub ?? null;
+ if (!is_string($client_id) || $client_id === '') {
+ return null;
+ }
+
+ $scope = $token->{'imsglobal.org.security.scope'} ?? '';
+ if (is_string($scope)) {
+ $scopes = preg_split('/\s+/', trim($scope)) ?: [];
+ } elseif (is_array($scope) && array_is_list($scope)) {
+ $scopes = [];
+ foreach ($scope as $value) {
+ if (!is_string($value)) {
+ return null;
+ }
+ $scopes[] = $value;
+ }
+ } else {
+ $scopes = [];
+ }
+
+ return new self($client_id, $scopes);
+ }
+
+ public function getClientId(): string
+ {
+ return $this->client_id;
+ }
+
+ /** @return list */
+ public function getScopes(): array
+ {
+ return $this->scopes;
+ }
+}
diff --git a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerActivityProgress.php b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerActivityProgress.php
new file mode 100644
index 000000000000..b86da11090da
--- /dev/null
+++ b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerActivityProgress.php
@@ -0,0 +1,22 @@
+initCmixUser();
- $params = $this->getLaunchParametersLTI13($loginData['redirect_uri'], $this->object->getProvider()->getClientId(), $this->object->getProvider()->getId(), $loginData['nonce']);
+ $targetLinkUri = $loginData['target_link_uri'] ?? $this->getTargetLinkUri();
+ $params = $this->getLaunchParametersLTI13($targetLinkUri, $this->object->getProvider()->getClientId(), $this->object->getProvider()->getId(), $loginData['nonce']);
if (isset($loginData['state'])) {
$params['state'] = $loginData['state'];
}
@@ -252,16 +253,17 @@ protected function getStartButtonTxt13(): string
$target = $this->object->getLaunchMethod() == "newWin" ? "_blank" : "_self";
$button = '';
$ltiMessageHint = (string) $this->object->getRefId() . ":" . CLIENT_ID;
+ $html = $this->dic->refinery()->encode()->htmlSpecialCharsAsEntities();
ilSession::set('lti_message_hint', $ltiMessageHint);
- $output = '';
@@ -289,13 +291,14 @@ protected function getEmbeddedAutoStartFormular(): string
$target = "_self";
$output = '';
$ltiMessageHint = (string) $this->object->getRefId() . ":" . CLIENT_ID;
+ $html = $this->dic->refinery()->encode()->htmlSpecialCharsAsEntities();
ilSession::set('lti_message_hint', $ltiMessageHint);
- $output = '';
@@ -404,6 +407,18 @@ protected function getLaunchParametersLTI13(string $endpoint, string $clientId,
);
}
+ private function getTargetLinkUri(): string
+ {
+ foreach (explode(';', $this->object->getCustomParams()) as $param) {
+ $parts = explode('=', $param, 2);
+ if (count($parts) === 2 && trim($parts[0]) === 'target_link_uri') {
+ return trim($parts[1]);
+ }
+ }
+
+ return $this->object->getProvider()->getProviderUrl();
+ }
+
public static function isEmbeddedLaunchRequest(): bool
{
global $DIC; /* @var \ILIAS\DI\Container $DIC */
diff --git a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeService.php b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeService.php
index d1143fe9f1c4..118f2fef04ab 100755
--- a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeService.php
+++ b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeService.php
@@ -29,6 +29,7 @@
class ilLTIConsumerGradeService extends ilLTIConsumerServiceBase
{
+ private ilLTIConsumerLineItemRepository $lineItemRepository;
/** Read-only access to Gradebook services */
public const GRADESERVICE_READ = 1;
@@ -54,6 +55,8 @@ class ilLTIConsumerGradeService extends ilLTIConsumerServiceBase
public function __construct()
{
parent::__construct();
+ global $DIC;
+ $this->lineItemRepository = new ilLTIConsumerLineItemRepository($DIC->database());
$this->id = 'gradebookservice';
$this->name = 'ilLTIConsumerGradeService';
}
@@ -67,10 +70,10 @@ public function getResources(): array
// Lineitems should be after lineitem.
if (empty($this->resources)) {
$this->resources = array();
- $this->resources[] = new ilLTIConsumerGradeServiceLineItem($this);
- $this->resources[] = new ilLTIConsumerGradeServiceLineItems($this);
- $this->resources[] = new ilLTIConsumerGradeServiceResults($this);
- $this->resources[] = new ilLTIConsumerGradeServiceScores($this);
+ $this->resources[] = new ilLTIConsumerGradeServiceLineItem($this, $this->lineItemRepository);
+ $this->resources[] = new ilLTIConsumerGradeServiceLineItems($this, $this->lineItemRepository);
+ $this->resources[] = new ilLTIConsumerGradeServiceResults($this, $this->lineItemRepository);
+ $this->resources[] = new ilLTIConsumerGradeServiceScores($this, $this->lineItemRepository);
}
return $this->resources;
}
@@ -81,12 +84,12 @@ public function getResources(): array
*/
public function getPermittedScopes(): array
{
- $scopes = array();
- $scopes[] = self::SCOPE_GRADESERVICE_LINEITEM;
- $scopes[] = self::SCOPE_GRADESERVICE_LINEITEM_READ;
- $scopes[] = self::SCOPE_GRADESERVICE_RESULT_READ;
- $scopes[] = self::SCOPE_GRADESERVICE_SCORE;
- return $scopes;
+ return [
+ self::SCOPE_GRADESERVICE_LINEITEM,
+ self::SCOPE_GRADESERVICE_LINEITEM_READ,
+ self::SCOPE_GRADESERVICE_RESULT_READ,
+ self::SCOPE_GRADESERVICE_SCORE
+ ];
}
/**
diff --git a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeServiceLineItem.php b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeServiceLineItem.php
index 36c6cbccbc7b..5e78fb5d2a90 100755
--- a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeServiceLineItem.php
+++ b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeServiceLineItem.php
@@ -29,7 +29,10 @@
class ilLTIConsumerGradeServiceLineItem extends ilLTIConsumerResourceBase
{
- public function __construct(ilLTIConsumerServiceBase $service)
+ public function __construct(
+ ilLTIConsumerServiceBase $service,
+ private readonly ilLTIConsumerLineItemRepository $lineItemRepository
+ )
{
parent::__construct($service);
$this->id = 'LineItem.item';
@@ -40,4 +43,281 @@ public function __construct(ilLTIConsumerServiceBase $service)
$this->methods[] = self::HTTP_PUT;
$this->methods[] = self::HTTP_DELETE;
}
+
+ public function execute(ilLTIConsumerServiceResponse $response): void
+ {
+ $params = $this->parseTemplate();
+ $contextId = (int) ($params['context_id'] ?? 0);
+ $itemId = (int) ($params['item_id'] ?? 0);
+
+ try {
+ $isRealObject = ilObject::_lookupType($itemId) === 'lti';
+
+ if ($response->getRequestMethod() === self::HTTP_GET) {
+ if ($isRealObject) {
+ $this->handleGetReal($response, $contextId, $itemId);
+ } else {
+ $this->handleGetStored($response, $contextId, $itemId);
+ }
+ } elseif ($response->getRequestMethod() === self::HTTP_PUT) {
+ $this->handlePut($response, $contextId, $itemId, $isRealObject);
+ } elseif ($response->getRequestMethod() === self::HTTP_DELETE) {
+ $this->handleDelete($response, $contextId, $itemId, $isRealObject);
+ } else {
+ $response->setCode(405);
+ }
+ } catch (ilLTIConsumerHttpException $e) {
+ $response->setCode($e->getCode());
+ $response->setReason($e->getMessage());
+ } catch (Throwable $e) {
+ $response->setCode(500);
+ $response->setReason($e->getMessage());
+ }
+ }
+
+ protected function handleGetReal(ilLTIConsumerServiceResponse $response, int $contextId, int $itemId): void
+ {
+ $token = $this->checkTool([
+ ilLTIConsumerGradeService::SCOPE_GRADESERVICE_LINEITEM,
+ ilLTIConsumerGradeService::SCOPE_GRADESERVICE_LINEITEM_READ
+ ]);
+ if (!$token) {
+ throw ilLTIConsumerHttpException::unauthorized();
+ }
+
+ $object = new ilObjLTIConsumer($itemId, false);
+ $provider = $object->getProvider();
+ if (!$provider || (!$provider->isGradeSynchronization() && !$provider->getHasOutcome())) {
+ throw ilLTIConsumerHttpException::forbidden('grade synchronization not enabled');
+ }
+ $this->checkProviderMatchesToken($provider, $token);
+
+ $lineItem = self::buildLineItemData($contextId, $itemId, $object);
+ $response->setContentType('application/vnd.ims.lis.v2.lineitem+json');
+ $response->setBody(json_encode($lineItem, JSON_UNESCAPED_SLASHES));
+ }
+
+ protected function handleGetStored(ilLTIConsumerServiceResponse $response, int $contextId, int $itemId): void
+ {
+ $token = $this->checkTool([
+ ilLTIConsumerGradeService::SCOPE_GRADESERVICE_LINEITEM,
+ ilLTIConsumerGradeService::SCOPE_GRADESERVICE_LINEITEM_READ
+ ]);
+ if (!$token) {
+ throw ilLTIConsumerHttpException::unauthorized();
+ }
+
+ $lineItem = $this->findStoredLineItem($itemId, $contextId, $token->getClientId());
+ if ($lineItem === null) {
+ throw ilLTIConsumerHttpException::notFound('LineItem not found');
+ }
+
+ $lineItemData = [
+ 'id' => self::buildLineItemUrl($contextId, $itemId),
+ 'label' => $lineItem->label,
+ 'scoreMaximum' => $lineItem->scoreMaximum,
+ 'resourceId' => $lineItem->resourceId,
+ 'resourceLinkId' => $lineItem->resourceLinkId,
+ 'tag' => $lineItem->tag
+ ];
+
+ $response->setContentType('application/vnd.ims.lis.v2.lineitem+json');
+ $response->setBody(json_encode($lineItemData, JSON_UNESCAPED_SLASHES));
+ }
+
+ protected function handlePut(ilLTIConsumerServiceResponse $response, int $contextId, int $itemId, bool $isRealObject): void
+ {
+ $token = $this->checkTool([
+ ilLTIConsumerGradeService::SCOPE_GRADESERVICE_LINEITEM
+ ]);
+ if (!$token) {
+ throw ilLTIConsumerHttpException::unauthorized();
+ }
+ $clientId = $token->getClientId();
+
+ $body = json_decode($response->getRequestData());
+ if (!is_object($body) || json_last_error() !== JSON_ERROR_NONE) {
+ throw ilLTIConsumerHttpException::badRequest('Invalid request body');
+ }
+ if (property_exists($body, 'resourceLinkId')) {
+ $resource_link_id = is_scalar($body->resourceLinkId) ? (string) $body->resourceLinkId : '';
+ if (!$this->isClientResourceLink($contextId, $clientId, $resource_link_id)) {
+ throw ilLTIConsumerHttpException::notFound('Resource link not found');
+ }
+ }
+
+ if ($isRealObject) {
+ $object = new ilObjLTIConsumer($itemId, false);
+ $provider = $object->getProvider();
+ if (!$provider || (!$provider->isGradeSynchronization() && !$provider->getHasOutcome())) {
+ throw ilLTIConsumerHttpException::forbidden('grade synchronization not enabled');
+ }
+ $this->checkProviderMatchesToken($provider, $token);
+
+ if (isset($body->label) && is_string($body->label) && $body->label !== '') {
+ $object->setTitle($body->label);
+ }
+ if (isset($body->scoreMaximum) && is_numeric($body->scoreMaximum) && (float) $body->scoreMaximum > 0) {
+ $object->setScoreMaximum((float) $body->scoreMaximum);
+ }
+ $object->update();
+
+ $lineItem = self::buildLineItemData($contextId, $itemId, $object);
+ $response->setContentType('application/vnd.ims.lis.v2.lineitem+json');
+ $response->setBody(json_encode($lineItem, JSON_UNESCAPED_SLASHES));
+ } else {
+ $lineItem = $this->findStoredLineItem($itemId, $contextId, $clientId);
+ if ($lineItem === null) {
+ throw ilLTIConsumerHttpException::notFound('LineItem not found');
+ }
+
+ $label = isset($body->label) && is_string($body->label) && $body->label !== ''
+ ? (string) $body->label : $lineItem->label;
+ $scoreMax = isset($body->scoreMaximum) && is_numeric($body->scoreMaximum) && (float) $body->scoreMaximum > 0
+ ? (float) $body->scoreMaximum : $lineItem->scoreMaximum;
+ $resourceId = isset($body->resourceId) ? (string) $body->resourceId : $lineItem->resourceId;
+ $resourceLinkId = isset($body->resourceLinkId) ? (string) $body->resourceLinkId : $lineItem->resourceLinkId;
+ $tag = isset($body->tag) ? (string) $body->tag : $lineItem->tag;
+ $lineItem = $lineItem->withValues($label, $scoreMax, $resourceId, $resourceLinkId, $tag);
+ $this->lineItemRepository->update($lineItem);
+
+ $lineItemData = [
+ 'id' => self::buildLineItemUrl($contextId, $itemId),
+ 'label' => $lineItem->label,
+ 'scoreMaximum' => $lineItem->scoreMaximum,
+ 'resourceId' => $lineItem->resourceId,
+ 'resourceLinkId' => $lineItem->resourceLinkId,
+ 'tag' => $lineItem->tag
+ ];
+
+ $response->setContentType('application/vnd.ims.lis.v2.lineitem+json');
+ $response->setBody(json_encode($lineItemData, JSON_UNESCAPED_SLASHES));
+ }
+ }
+
+ protected function handleDelete(ilLTIConsumerServiceResponse $response, int $contextId, int $itemId, bool $isRealObject): void
+ {
+ $token = $this->checkTool([
+ ilLTIConsumerGradeService::SCOPE_GRADESERVICE_LINEITEM
+ ]);
+ if (!$token) {
+ throw ilLTIConsumerHttpException::unauthorized();
+ }
+ $clientId = $token->getClientId();
+
+ if ($isRealObject) {
+ $response->setCode(405);
+ return;
+ } else {
+ $lineItem = $this->findStoredLineItem($itemId, $contextId, $clientId);
+ if ($lineItem === null) {
+ throw ilLTIConsumerHttpException::notFound('LineItem not found');
+ }
+ $this->lineItemRepository->disable($lineItem);
+ }
+
+ $response->setCode(200);
+ }
+
+ protected function findStoredLineItem(int $itemId, int $contextId, string $clientId): ?ilLTIConsumerLineItem
+ {
+ $storedId = -$itemId;
+ if ($storedId <= 0) {
+ return null;
+ }
+
+ return $this->lineItemRepository->get($storedId, $contextId, $clientId);
+ }
+
+ protected function checkProviderMatchesToken(ilLTIConsumeProvider $provider, ilLTIConsumerAccessToken $token): void
+ {
+ if ($provider->getClientId() !== $token->getClientId()) {
+ throw ilLTIConsumerHttpException::forbidden('invalid clientId');
+ }
+ }
+
+ protected function isClientResourceLink(int $context_id, string $client_id, string $resource_link_id): bool
+ {
+ $resource_link_ref_id = (int) $resource_link_id;
+ if ($resource_link_ref_id <= 0) {
+ return false;
+ }
+
+ global $DIC;
+ $tree = $DIC->repositoryTree();
+ $node_data = $tree->getNodeData($resource_link_ref_id);
+ if (!isset($node_data['type']) || $node_data['type'] !== 'lti' ||
+ !in_array($context_id, $tree->getPathId($resource_link_ref_id), true)) {
+ return false;
+ }
+
+ $object_id = ilObject::_lookupObjId($resource_link_ref_id);
+ if (!$object_id) {
+ return false;
+ }
+
+ $provider = (new ilObjLTIConsumer($object_id, false))->getProvider();
+ return $provider !== null && $provider->getClientId() === $client_id;
+ }
+
+ /**
+ * @return array{id: string, label: string, scoreMaximum: float, resourceId: string, resourceLinkId: string}
+ */
+ public static function buildLineItemData(int $contextId, int $itemId, ilObjLTIConsumer $object): array
+ {
+ return [
+ 'id' => self::buildLineItemUrl($contextId, $itemId),
+ 'label' => $object->getTitle(),
+ 'scoreMaximum' => $object->getScoreMaximum(),
+ 'resourceId' => (string) $itemId,
+ 'resourceLinkId' => self::getResourceLinkId($contextId, $itemId)
+ ];
+ }
+
+ protected static function getResourceLinkId(int $contextId, int $itemId): string
+ {
+ global $DIC;
+
+ $refs = ilObject::_getAllReferences($itemId);
+ foreach ($refs as $refId) {
+ $refId = (int) $refId;
+ $path = $DIC->repositoryTree()->getPathId($refId);
+ if (in_array($contextId, $path, true)) {
+ return (string) $refId;
+ }
+ }
+
+ $refId = (int) current($refs);
+ return $refId > 0 ? (string) $refId : '';
+ }
+
+ public static function buildLineItemUrl(int $contextId, int $itemId): string
+ {
+ return self::buildLineItemsUrl($contextId) . "/{$itemId}/lineitem";
+ }
+
+ public static function buildLineItemsUrl(int $contextId): string
+ {
+ return self::getServiceRootUrl() . "/ltiservices.php/gradeservice/{$contextId}/lineitems";
+ }
+
+ /**
+ * AGS 2.0 §3.2.3 asks for a stable line item URL and §3.3.4.3 requires the id a
+ * tool reads back to be identical to the lineitem claim it received at launch.
+ * Both are built from here, so the base must not depend on the current request:
+ * ilObjLTIConsumer::getIliasHttpPath() derives it from REQUEST_URI, which already
+ * contains "/gradeservice/{context}/lineitems/..." under the PATH_INFO routing of
+ * ltiservices.php, and HTTP_HOST does not survive a reverse proxy. The configured
+ * http_path is the same source ILIAS uses for its own absolute links.
+ */
+ public static function getServiceRootUrl(): string
+ {
+ global $DIC;
+
+ $http_path = ilContext::modifyHttpPath(
+ $DIC['ilIliasIniFile']->readVariable('server', 'http_path')
+ );
+
+ return (new \ILIAS\Data\Factory())->uri(rtrim($http_path, '/'))->getBaseURI();
+ }
}
diff --git a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeServiceLineItems.php b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeServiceLineItems.php
index 41faf0624175..137b586e5472 100755
--- a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeServiceLineItems.php
+++ b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeServiceLineItems.php
@@ -29,7 +29,10 @@
class ilLTIConsumerGradeServiceLineItems extends ilLTIConsumerResourceBase
{
- public function __construct(ilLTIConsumerServiceBase $service)
+ public function __construct(
+ ilLTIConsumerServiceBase $service,
+ private readonly ilLTIConsumerLineItemRepository $lineItemRepository
+ )
{
parent::__construct($service);
$this->id = 'LineItem.collection';
@@ -40,4 +43,264 @@ public function __construct(ilLTIConsumerServiceBase $service)
$this->methods[] = self::HTTP_GET;
$this->methods[] = self::HTTP_POST;
}
+
+ public function execute(ilLTIConsumerServiceResponse $response): void
+ {
+ $params = $this->parseTemplate();
+ $contextId = (int) ($params['context_id'] ?? 0);
+
+ try {
+ if ($response->getRequestMethod() === self::HTTP_GET) {
+ $this->handleGet($response, $contextId);
+ } elseif ($response->getRequestMethod() === self::HTTP_POST) {
+ $this->handlePost($response, $contextId);
+ } else {
+ $response->setCode(405);
+ }
+ } catch (ilLTIConsumerHttpException $e) {
+ $response->setCode($e->getCode());
+ $response->setReason($e->getMessage());
+ } catch (Throwable $e) {
+ $response->setCode(500);
+ $response->setReason($e->getMessage());
+ }
+ }
+
+ protected function handleGet(ilLTIConsumerServiceResponse $response, int $contextId): void
+ {
+ $token = $this->checkTool([
+ ilLTIConsumerGradeService::SCOPE_GRADESERVICE_LINEITEM,
+ ilLTIConsumerGradeService::SCOPE_GRADESERVICE_LINEITEM_READ
+ ]);
+ if (!$token) {
+ throw ilLTIConsumerHttpException::unauthorized();
+ }
+ $clientId = $token->getClientId();
+
+ global $DIC;
+ $tree = $DIC->repositoryTree();
+ $nodeData = $tree->getNodeData($contextId);
+ if (!$nodeData) {
+ throw ilLTIConsumerHttpException::notFound('Context not found');
+ }
+
+ $lineItems = [];
+ $filters = $this->getFilters();
+
+ $subtree = $tree->getSubTree($nodeData);
+ foreach ($subtree as $node) {
+ if ($node['type'] !== 'lti') {
+ continue;
+ }
+ $objId = ilObject::_lookupObjId((int) $node['child']);
+ if (!$objId) {
+ continue;
+ }
+ $object = new ilObjLTIConsumer($objId, false);
+ $provider = $object->getProvider();
+ if (!$provider || (!$provider->isGradeSynchronization() && !$provider->getHasOutcome())) {
+ continue;
+ }
+ if ($provider->getClientId() !== $clientId) {
+ continue;
+ }
+ $lineItems[] = ilLTIConsumerGradeServiceLineItem::buildLineItemData($contextId, $objId, $object);
+ }
+
+ foreach ($this->lineItemRepository->getForContextAndClient($contextId, $clientId) as $storedLineItem) {
+ $lineItems[] = [
+ 'id' => ilLTIConsumerGradeServiceLineItem::buildLineItemUrl($contextId, -$storedLineItem->id),
+ 'label' => $storedLineItem->label,
+ 'scoreMaximum' => $storedLineItem->scoreMaximum,
+ 'resourceId' => $storedLineItem->resourceId,
+ 'resourceLinkId' => $storedLineItem->resourceLinkId,
+ 'tag' => $storedLineItem->tag
+ ];
+ }
+
+ $lineItems = $this->filterLineItems($lineItems, $filters);
+ $offset = ($filters['page'] - 1) * $filters['limit'];
+ $has_next_page = $filters['limit'] > 0 && count($lineItems) > $offset + $filters['limit'];
+ if ($filters['limit'] > 0) {
+ $lineItems = array_slice($lineItems, $offset, $filters['limit']);
+ }
+
+ $response->setContentType('application/vnd.ims.lis.v2.lineitemcontainer+json');
+ if ($has_next_page) {
+ $this->addNextPageHeader($response, $contextId, $filters);
+ }
+ $response->setBody(json_encode($lineItems, JSON_UNESCAPED_SLASHES));
+ }
+
+ protected function handlePost(ilLTIConsumerServiceResponse $response, int $contextId): void
+ {
+ $token = $this->checkTool([
+ ilLTIConsumerGradeService::SCOPE_GRADESERVICE_LINEITEM
+ ]);
+ if (!$token) {
+ throw ilLTIConsumerHttpException::unauthorized();
+ }
+ $clientId = $token->getClientId();
+
+ $body = json_decode($response->getRequestData());
+ if (!is_object($body) || json_last_error() !== JSON_ERROR_NONE) {
+ throw ilLTIConsumerHttpException::badRequest('Invalid request body');
+ }
+
+ if (!$this->contextContainsClientTool($contextId, $clientId)) {
+ throw ilLTIConsumerHttpException::forbidden('Context not available for client');
+ }
+
+ if (!property_exists($body, 'label') || !is_string($body->label) || trim($body->label) === '') {
+ throw ilLTIConsumerHttpException::badRequest('LineItem label is required');
+ }
+ if (!property_exists($body, 'scoreMaximum') || !is_numeric($body->scoreMaximum) ||
+ (float) $body->scoreMaximum <= 0) {
+ throw ilLTIConsumerHttpException::badRequest('LineItem scoreMaximum must be greater than zero');
+ }
+
+ $label = $body->label;
+ $scoreMax = (float) $body->scoreMaximum;
+ $resourceId = isset($body->resourceId) ? (string) $body->resourceId : '';
+ $resourceLinkId = isset($body->resourceLinkId) && is_scalar($body->resourceLinkId)
+ ? (string) $body->resourceLinkId : '';
+ $tag = isset($body->tag) ? (string) $body->tag : '';
+ if (property_exists($body, 'resourceLinkId') &&
+ (!is_scalar($body->resourceLinkId) || !$this->isClientResourceLink($contextId, $clientId, $resourceLinkId))) {
+ throw ilLTIConsumerHttpException::notFound('Resource link not found');
+ }
+
+ $lineItem = $this->lineItemRepository->create(
+ $contextId,
+ $clientId,
+ $label,
+ $scoreMax,
+ $resourceId,
+ $resourceLinkId,
+ $tag
+ );
+ $lineItemData = [
+ 'id' => ilLTIConsumerGradeServiceLineItem::buildLineItemUrl($contextId, -$lineItem->id),
+ 'label' => $lineItem->label,
+ 'scoreMaximum' => $lineItem->scoreMaximum,
+ 'resourceId' => $lineItem->resourceId,
+ 'resourceLinkId' => $lineItem->resourceLinkId,
+ 'tag' => $lineItem->tag
+ ];
+
+ $response->setCode(201);
+ $response->setContentType('application/vnd.ims.lis.v2.lineitem+json');
+ $response->setBody(json_encode($lineItemData, JSON_UNESCAPED_SLASHES));
+ }
+
+ /**
+ * @return array{tag: string, resourceId: string, resourceLinkId: string, limit: int, page: int}
+ */
+ protected function getFilters(): array
+ {
+ global $DIC;
+
+ $query = $DIC->http()->wrapper()->query();
+ $string = $DIC->refinery()->kindlyTo()->string();
+ $limit = $query->has('limit') ? $query->retrieve('limit', $string) : '';
+
+ return [
+ 'tag' => $query->has('tag') ? $query->retrieve('tag', $string) : '',
+ 'resourceId' => $query->has('resource_id') ? $query->retrieve('resource_id', $string) : '',
+ 'resourceLinkId' => $query->has('resource_link_id') ? $query->retrieve('resource_link_id', $string) : '',
+ 'limit' => is_numeric($limit) ? max(0, (int) $limit) : 0,
+ 'page' => $query->has('page') && is_numeric($query->retrieve('page', $string))
+ ? max(1, (int) $query->retrieve('page', $string)) : 1
+ ];
+ }
+
+ protected function filterLineItems(array $lineItems, array $filters): array
+ {
+ $filtered = array_values(array_filter($lineItems, static function (array $item) use ($filters): bool {
+ if ($filters['tag'] !== '' && ($item['tag'] ?? '') !== $filters['tag']) {
+ return false;
+ }
+ if ($filters['resourceId'] !== '' && ($item['resourceId'] ?? '') !== $filters['resourceId']) {
+ return false;
+ }
+ if ($filters['resourceLinkId'] !== '' && ($item['resourceLinkId'] ?? '') !== $filters['resourceLinkId']) {
+ return false;
+ }
+ return true;
+ }));
+
+ return $filtered;
+ }
+
+ protected function isClientResourceLink(int $context_id, string $client_id, string $resource_link_id): bool
+ {
+ $resource_link_ref_id = (int) $resource_link_id;
+ if ($resource_link_ref_id <= 0) {
+ return false;
+ }
+
+ global $DIC;
+ $tree = $DIC->repositoryTree();
+ $node_data = $tree->getNodeData($resource_link_ref_id);
+ if (!isset($node_data['type']) || $node_data['type'] !== 'lti' ||
+ !in_array($context_id, $tree->getPathId($resource_link_ref_id), true)) {
+ return false;
+ }
+
+ $object_id = ilObject::_lookupObjId($resource_link_ref_id);
+ if (!$object_id) {
+ return false;
+ }
+
+ $provider = (new ilObjLTIConsumer($object_id, false))->getProvider();
+ return $provider !== null && $provider->getClientId() === $client_id;
+ }
+
+ /** @param array{tag: string, resourceId: string, resourceLinkId: string, limit: int, page: int} $filters */
+ protected function addNextPageHeader(ilLTIConsumerServiceResponse $response, int $context_id, array $filters): void
+ {
+ $query = ['limit' => $filters['limit'], 'page' => $filters['page'] + 1];
+ if ($filters['tag'] !== '') {
+ $query['tag'] = $filters['tag'];
+ }
+ if ($filters['resourceId'] !== '') {
+ $query['resource_id'] = $filters['resourceId'];
+ }
+ if ($filters['resourceLinkId'] !== '') {
+ $query['resource_link_id'] = $filters['resourceLinkId'];
+ }
+
+ $url = ilLTIConsumerGradeServiceLineItem::buildLineItemsUrl($context_id);
+ $response->addAdditionalHeader('Link: <' . $url . '?' . http_build_query($query) . '>; rel="next"');
+ }
+
+ protected function contextContainsClientTool(int $contextId, string $clientId): bool
+ {
+ global $DIC;
+
+ $tree = $DIC->repositoryTree();
+ $nodeData = $tree->getNodeData($contextId);
+ if (!$nodeData) {
+ return false;
+ }
+
+ foreach ($tree->getSubTree($nodeData) as $node) {
+ if ($node['type'] !== 'lti') {
+ continue;
+ }
+ $objId = ilObject::_lookupObjId((int) $node['child']);
+ if (!$objId) {
+ continue;
+ }
+ $object = new ilObjLTIConsumer($objId, false);
+ $provider = $object->getProvider();
+ if ($provider && ($provider->isGradeSynchronization() || $provider->getHasOutcome()) &&
+ $provider->getClientId() === $clientId) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
}
diff --git a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeServiceResults.php b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeServiceResults.php
index 1f2a419d4b33..a83385a5a31f 100755
--- a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeServiceResults.php
+++ b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeServiceResults.php
@@ -29,7 +29,10 @@
class ilLTIConsumerGradeServiceResults extends ilLTIConsumerResourceBase
{
- public function __construct(ilLTIConsumerServiceBase $service)
+ public function __construct(
+ ilLTIConsumerServiceBase $service,
+ private readonly ilLTIConsumerLineItemRepository $lineItemRepository
+ )
{
parent::__construct($service);
$this->id = 'Result.collection';
@@ -38,4 +41,338 @@ public function __construct(ilLTIConsumerServiceBase $service)
$this->formats[] = 'application/vnd.ims.lis.v2.resultcontainer+json';
$this->methods[] = 'GET';
}
+
+ public function execute(ilLTIConsumerServiceResponse $response): void
+ {
+ $params = $this->parseTemplate();
+ $contextId = (int) ($params['context_id'] ?? 0);
+ $itemId = (int) ($params['item_id'] ?? 0);
+
+ try {
+ $token = $this->checkTool([
+ ilLTIConsumerGradeService::SCOPE_GRADESERVICE_RESULT_READ
+ ]);
+ if (!$token) {
+ throw ilLTIConsumerHttpException::unauthorized();
+ }
+ $clientId = $token->getClientId();
+
+ global $DIC;
+ $ilDB = $DIC->database();
+ $scoreMaximum = 1.0;
+ $filters = $this->getFilters();
+ $filterUserId = null;
+
+ if (ilObject::_lookupType($itemId) === 'lti') {
+ $object = new ilObjLTIConsumer($itemId, false);
+ $provider = $object->getProvider();
+ if (!$provider || (!$provider->isGradeSynchronization() && !$provider->getHasOutcome())) {
+ throw ilLTIConsumerHttpException::forbidden('grade synchronization not enabled');
+ }
+ if ($provider->getClientId() !== $clientId) {
+ throw ilLTIConsumerHttpException::forbidden('invalid clientId');
+ }
+ $scoreMaximum = $object->getScoreMaximum() > 0 ? $object->getScoreMaximum() : 1.0;
+ $filterUserId = $filters['userId'] !== ''
+ ? $this->resolveUserIdFromLtiIdent($itemId, $filters['userId'])
+ : null;
+ } else {
+ $storedId = -$itemId;
+ if ($storedId <= 0) {
+ throw ilLTIConsumerHttpException::notFound('LineItem not found');
+ }
+
+ $stored_line_item = $this->lineItemRepository->get($storedId, $contextId, $clientId);
+ if ($stored_line_item === null) {
+ throw ilLTIConsumerHttpException::notFound('LineItem not found');
+ }
+
+ $lti_object = $this->getStoredLineItemLtiObject($contextId, $stored_line_item, $clientId);
+ $filterUserId = $filters['userId'] !== ''
+ ? $this->resolveUserIdFromLtiIdent($lti_object->getId(), $filters['userId'])
+ : null;
+ $results = $this->getStoredResults(
+ $ilDB,
+ $contextId,
+ $itemId,
+ $stored_line_item,
+ $lti_object->getId(),
+ $lti_object->getProvider()->getPrivacyIdent(),
+ $filterUserId,
+ $filters
+ );
+ $response->setContentType('application/vnd.ims.lis.v2.resultcontainer+json');
+ $this->addNextPageHeader($response, $contextId, $itemId, $filters, $results['has_next_page']);
+ $response->setBody(json_encode($results['items'], JSON_UNESCAPED_SLASHES));
+ return;
+ }
+
+ $privacyIdent = $provider->getPrivacyIdent();
+
+ $query = 'SELECT * FROM lti_consumer_results'
+ . ' WHERE obj_id = ' . $ilDB->quote($itemId, 'integer');
+ $res = $ilDB->query($query);
+
+ $resultsArr = [];
+ $lineItemUrl = ilLTIConsumerGradeServiceLineItem::buildLineItemUrl($contextId, $itemId);
+ while ($row = $ilDB->fetchAssoc($res)) {
+ $userId = (int) $row['usr_id'];
+
+ $identQuery = 'SELECT usr_ident FROM cmix_users'
+ . ' WHERE obj_id = ' . $ilDB->quote($itemId, 'integer')
+ . ' AND usr_id = ' . $ilDB->quote($userId, 'integer');
+ $identRes = $ilDB->query($identQuery);
+ $identRow = $ilDB->fetchAssoc($identRes);
+ $userIdent = $identRow['usr_ident'] ?? (string) $userId;
+ if ($filterUserId !== null && $filterUserId !== $userId) {
+ continue;
+ }
+ if ($filters['userId'] !== '' && $filterUserId === null && !$this->matchesLtiUserIdent($itemId, $userId, $userIdent, $filters['userId'])) {
+ continue;
+ }
+
+ $resultValue = $row['result'];
+ if ($resultValue !== null) {
+ $ltiUserId = $this->getLtiUserId($privacyIdent, $userId, $userIdent);
+
+ $latestGradeQuery = 'SELECT score_given, score_maximum FROM lti_consumer_grades'
+ . ' WHERE obj_id = ' . $ilDB->quote($itemId, 'integer')
+ . ' AND usr_id = ' . $ilDB->quote($userId, 'integer')
+ . ' AND score_given IS NOT NULL'
+ . ' AND score_maximum IS NOT NULL'
+ . ' ORDER BY lti_timestamp DESC, stored DESC';
+ $latestGradeRes = $ilDB->query($latestGradeQuery);
+ $latestGradeRow = $ilDB->fetchAssoc($latestGradeRes);
+
+ $resultScore = $latestGradeRow !== null
+ ? (float) $latestGradeRow['score_given']
+ : (float) $resultValue * $scoreMaximum;
+ $resultMaximum = $latestGradeRow !== null && (float) $latestGradeRow['score_maximum'] > 0
+ ? (float) $latestGradeRow['score_maximum']
+ : $scoreMaximum;
+
+ $resultsArr[] = [
+ 'id' => $lineItemUrl . '/results'
+ . '?user_id=' . rawurlencode($ltiUserId),
+ 'scoreOf' => $lineItemUrl,
+ 'userId' => $ltiUserId,
+ 'resultScore' => $resultScore,
+ 'resultMaximum' => $resultMaximum
+ ];
+ }
+ }
+
+ if (empty($resultsArr)) {
+ $gradeQuery = 'SELECT * FROM lti_consumer_grades'
+ . ' WHERE obj_id = ' . $ilDB->quote($itemId, 'integer');
+ if ($filterUserId !== null) {
+ $gradeQuery .= ' AND usr_id = ' . $ilDB->quote($filterUserId, 'integer');
+ }
+ $gradeQuery .= ' ORDER BY lti_timestamp DESC, stored DESC';
+ $gradeRes = $ilDB->query($gradeQuery);
+ $seenUsers = [];
+ while ($gradeRow = $ilDB->fetchAssoc($gradeRes)) {
+ $userId = (int) $gradeRow['usr_id'];
+ if (isset($seenUsers[$userId])) {
+ continue;
+ }
+ $seenUsers[$userId] = true;
+
+ // the most recent submission for this user is a cleared score (§3.4.4):
+ // it must not fall back to an older, non-null grade
+ if ($gradeRow['score_given'] === null || $gradeRow['score_maximum'] === null) {
+ continue;
+ }
+
+ $identQuery = 'SELECT usr_ident FROM cmix_users'
+ . ' WHERE obj_id = ' . $ilDB->quote($itemId, 'integer')
+ . ' AND usr_id = ' . $ilDB->quote($userId, 'integer');
+ $identRes = $ilDB->query($identQuery);
+ $identRow = $ilDB->fetchAssoc($identRes);
+ $userIdent = $identRow['usr_ident'] ?? (string) $userId;
+ if ($filterUserId === null && $filters['userId'] !== '' && !$this->matchesLtiUserIdent($itemId, $userId, $userIdent, $filters['userId'])) {
+ continue;
+ }
+
+ $ltiUserId = $this->getLtiUserId($privacyIdent, $userId, $userIdent);
+ $resultMaximum = (float) $gradeRow['score_maximum'];
+ $resultsArr[] = [
+ 'id' => $lineItemUrl . '/results'
+ . '?user_id=' . rawurlencode($ltiUserId),
+ 'scoreOf' => $lineItemUrl,
+ 'userId' => $ltiUserId,
+ 'resultScore' => (float) $gradeRow['score_given'],
+ 'resultMaximum' => $resultMaximum > 0 ? $resultMaximum : $scoreMaximum
+ ];
+ }
+ }
+
+ $offset = ($filters['page'] - 1) * $filters['limit'];
+ $has_next_page = $filters['limit'] > 0 && count($resultsArr) > $offset + $filters['limit'];
+ if ($filters['limit'] > 0) {
+ $resultsArr = array_slice($resultsArr, $offset, $filters['limit']);
+ }
+
+ $response->setContentType('application/vnd.ims.lis.v2.resultcontainer+json');
+ $this->addNextPageHeader($response, $contextId, $itemId, $filters, $has_next_page);
+ $response->setBody(json_encode($resultsArr, JSON_UNESCAPED_SLASHES));
+ } catch (ilLTIConsumerHttpException $e) {
+ $response->setCode($e->getCode());
+ $response->setReason($e->getMessage());
+ } catch (Throwable $e) {
+ $response->setCode(500);
+ $response->setReason($e->getMessage());
+ }
+ }
+
+ /**
+ * @return array{userId: string, limit: int, page: int}
+ */
+ protected function getFilters(): array
+ {
+ global $DIC;
+
+ $query = $DIC->http()->wrapper()->query();
+ $string = $DIC->refinery()->kindlyTo()->string();
+ $limit = $query->has('limit') ? $query->retrieve('limit', $string) : '';
+
+ return [
+ 'userId' => $query->has('user_id') ? $query->retrieve('user_id', $string) : '',
+ 'limit' => is_numeric($limit) ? max(0, (int) $limit) : 0,
+ 'page' => $query->has('page') && is_numeric($query->retrieve('page', $string))
+ ? max(1, (int) $query->retrieve('page', $string)) : 1
+ ];
+ }
+
+ protected function getStoredLineItemLtiObject(
+ int $context_id,
+ ilLTIConsumerLineItem $line_item,
+ string $client_id
+ ): ilObjLTIConsumer {
+ $resource_link_ref_id = (int) $line_item->resourceLinkId;
+ if ($resource_link_ref_id <= 0) {
+ throw ilLTIConsumerHttpException::notFound('Resource link not found');
+ }
+
+ global $DIC;
+ $tree = $DIC->repositoryTree();
+ $node_data = $tree->getNodeData($resource_link_ref_id);
+ if (!isset($node_data['type']) || $node_data['type'] !== 'lti' ||
+ !in_array($context_id, $tree->getPathId($resource_link_ref_id), true)) {
+ throw ilLTIConsumerHttpException::notFound('Resource link not found');
+ }
+
+ $lti_object_id = ilObject::_lookupObjId($resource_link_ref_id);
+ if (!$lti_object_id) {
+ throw ilLTIConsumerHttpException::notFound('Resource link not found');
+ }
+
+ $lti_object = new ilObjLTIConsumer($lti_object_id, false);
+ $provider = $lti_object->getProvider();
+ if (!$provider || $provider->getClientId() !== $client_id) {
+ throw ilLTIConsumerHttpException::forbidden('invalid clientId');
+ }
+
+ return $lti_object;
+ }
+
+ /**
+ * @param array{userId: string, limit: int, page: int} $filters
+ * @return array{items: list>, has_next_page: bool}
+ */
+ protected function getStoredResults(
+ ilDBInterface $db,
+ int $context_id,
+ int $item_id,
+ ilLTIConsumerLineItem $line_item,
+ int $lti_object_id,
+ int $privacy_ident,
+ ?int $filter_user_id,
+ array $filters
+ ): array {
+ $query = 'SELECT score_given, score_maximum, usr_id FROM lti_consumer_grades'
+ . ' WHERE obj_id = ' . $db->quote($item_id, 'integer')
+ . ' ORDER BY lti_timestamp DESC, stored DESC';
+ $result = $db->query($query);
+ $line_item_url = ilLTIConsumerGradeServiceLineItem::buildLineItemUrl($context_id, $item_id);
+ $results = [];
+ $seen_user_ids = [];
+ while ($row = $db->fetchAssoc($result)) {
+ $user_id = (int) $row['usr_id'];
+ if (isset($seen_user_ids[$user_id]) ||
+ ($filter_user_id !== null && $filter_user_id !== $user_id)) {
+ continue;
+ }
+
+ $seen_user_ids[$user_id] = true;
+
+ // the most recent submission for this user is a cleared score (§3.4.4):
+ // it must not fall back to an older, non-null grade
+ if ($row['score_given'] === null || $row['score_maximum'] === null) {
+ continue;
+ }
+
+ $ident_query = 'SELECT usr_ident FROM cmix_users'
+ . ' WHERE obj_id = ' . $db->quote($lti_object_id, 'integer')
+ . ' AND usr_id = ' . $db->quote($user_id, 'integer');
+ $ident_result = $db->query($ident_query);
+ $ident_row = $db->fetchAssoc($ident_result);
+ $user_ident = $ident_row['usr_ident'] ?? (string) $user_id;
+ if ($filter_user_id === null && $filters['userId'] !== '' &&
+ !$this->matchesLtiUserIdent($lti_object_id, $user_id, $user_ident, $filters['userId'])) {
+ continue;
+ }
+
+ $score_maximum = (float) $row['score_maximum'];
+ $lti_user_id = $this->getLtiUserId($privacy_ident, $user_id, $user_ident);
+ $results[] = [
+ 'id' => $line_item_url . '/results?user_id=' . rawurlencode($lti_user_id),
+ 'scoreOf' => $line_item_url,
+ 'userId' => $lti_user_id,
+ 'resultScore' => (float) $row['score_given'],
+ 'resultMaximum' => $score_maximum > 0 ? $score_maximum : $line_item->scoreMaximum
+ ];
+ }
+
+ $offset = ($filters['page'] - 1) * $filters['limit'];
+ $has_next_page = $filters['limit'] > 0 && count($results) > $offset + $filters['limit'];
+ if ($filters['limit'] > 0) {
+ $results = array_slice($results, $offset, $filters['limit']);
+ }
+
+ return ['items' => $results, 'has_next_page' => $has_next_page];
+ }
+
+ /** @param array{userId: string, limit: int, page: int} $filters */
+ protected function addNextPageHeader(
+ ilLTIConsumerServiceResponse $response,
+ int $context_id,
+ int $item_id,
+ array $filters,
+ bool $has_next_page
+ ): void {
+ if (!$has_next_page) {
+ return;
+ }
+
+ $query = ['limit' => $filters['limit'], 'page' => $filters['page'] + 1];
+ if ($filters['userId'] !== '') {
+ $query['user_id'] = $filters['userId'];
+ }
+ $url = ilLTIConsumerGradeServiceLineItem::buildLineItemUrl($context_id, $item_id) . '/results';
+ $response->addAdditionalHeader('Link: <' . $url . '?' . http_build_query($query) . '>; rel="next"');
+ }
+
+ protected function getLtiUserId(int $privacyIdent, int $userId, string $userIdent): string
+ {
+ $userObj = new ilObjUser($userId);
+ $ltiUserId = ilCmiXapiUser::getIdentAsId($privacyIdent, $userObj);
+ if ($privacyIdent === ilObjCmiXapi::PRIVACY_IDENT_IL_UUID_RANDOM) {
+ $randomPart = strstr($userIdent, '@' . ilCmiXapiUser::getIliasUuid(), true);
+ if ($randomPart !== false && $randomPart !== '') {
+ $ltiUserId = $randomPart;
+ }
+ }
+ return $ltiUserId !== '' ? $ltiUserId : $userIdent;
+ }
}
diff --git a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeServiceScores.php b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeServiceScores.php
index a6ecbf0d1ecd..43f221fe0143 100755
--- a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeServiceScores.php
+++ b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeServiceScores.php
@@ -29,7 +29,10 @@
class ilLTIConsumerGradeServiceScores extends ilLTIConsumerResourceBase
{
- public function __construct(ilLTIConsumerServiceBase $service)
+ public function __construct(
+ ilLTIConsumerServiceBase $service,
+ private readonly ilLTIConsumerLineItemRepository $line_item_repository
+ )
{
parent::__construct($service);
$this->id = 'Score.collection';
@@ -46,40 +49,92 @@ public function __construct(ilLTIConsumerServiceBase $service)
public function execute(ilLTIConsumerServiceResponse $response): void
{
$params = $this->parseTemplate();
- $contextId = $params['context_id'];
- $itemId = $params['item_id'];
+ $context_id = (int) ($params['context_id'] ?? 0);
+ $item_id = (int) ($params['item_id'] ?? 0);
- ilObjLTIConsumer::getLogger()->info("contextId: " . $contextId);
- ilObjLTIConsumer::getLogger()->info("objId: " . $itemId);
+ ilObjLTIConsumer::getLogger()->info("contextId: " . $context_id);
+ ilObjLTIConsumer::getLogger()->info("objId: " . $item_id);
ilObjLTIConsumer::getLogger()->info("request data: " . $response->getRequestData());
- // GET is disabled by the moment, but we have the code ready
- // for a future implementation.
-
- //$container = empty($contentType) || ($contentType === $this->formats[0]);
-
- $typeid = 0;
-
$scope = ilLTIConsumerGradeService::SCOPE_GRADESERVICE_SCORE;
try {
$token = $this->checkTool(array($scope));
if (is_null($token)) {
- throw new Exception('invalid request', 401);
+ throw ilLTIConsumerHttpException::unauthorized();
}
-
- // Bug in Moodle as tool provider, should accept only "204 No Content" but schedules grade sync task will notices a failed status if not exactly 200
- // see: http://www.imsglobal.org/spec/lti-ags/v2p0#score-service-scope-and-allowed-http-methods
- //$response->setCode(204); // correct
- $returnCode = 200;
- $returnCode = $this->checkScore($response->getRequestData(), (int) $itemId);
- $response->setCode($returnCode); // not really correct
- } catch (Exception $e) {
+ if (ilObject::_lookupType($item_id) === 'lti') {
+ $this->checkToolMatchesObject($item_id, $token);
+ $this->checkScore($response->getRequestData(), $item_id);
+ } else {
+ $this->checkStoredLineItemScore($response->getRequestData(), $context_id, $item_id, $token);
+ }
+ $response->setCode(204);
+ } catch (ilLTIConsumerHttpException $e) {
$response->setCode($e->getCode());
$response->setReason($e->getMessage());
+ } catch (Throwable $e) {
+ $response->setCode(500);
+ $response->setReason($e->getMessage());
+ }
+ }
+
+ protected function checkToolMatchesObject(int $objId, ilLTIConsumerAccessToken $token): void
+ {
+ $clientId = $token->getClientId();
+
+ if (ilObject::_lookupType($objId) !== 'lti') {
+ throw ilLTIConsumerHttpException::notFound('Tool for Object not available');
+ }
+
+ $ltiObject = new ilObjLTIConsumer($objId, false);
+ $provider = $ltiObject->getProvider();
+ if (!$provider instanceof ilLTIConsumeProvider) {
+ throw ilLTIConsumerHttpException::notFound('Tool for Object not available');
}
+
+ if ($provider->getClientId() !== $clientId) {
+ throw ilLTIConsumerHttpException::forbidden('invalid clientId');
+ }
+
+ if (!$provider->isGradeSynchronization() && !$provider->getHasOutcome()) {
+ throw ilLTIConsumerHttpException::forbidden('grade synchronization not enabled');
+ }
+ }
+
+ protected function checkStoredLineItemScore(
+ string $request_data,
+ int $context_id,
+ int $item_id,
+ ilLTIConsumerAccessToken $token
+ ): void {
+ $stored_line_item = $this->line_item_repository->get(-$item_id, $context_id, $token->getClientId());
+ if ($item_id >= 0 || $stored_line_item === null) {
+ throw ilLTIConsumerHttpException::notFound('LineItem not found');
+ }
+
+ $resource_link_ref_id = (int) $stored_line_item->resourceLinkId;
+ if ($resource_link_ref_id <= 0) {
+ throw ilLTIConsumerHttpException::notFound('Resource link not found');
+ }
+
+ global $DIC;
+ $tree = $DIC->repositoryTree();
+ $node_data = $tree->getNodeData($resource_link_ref_id);
+ if (!isset($node_data['type']) || $node_data['type'] !== 'lti' ||
+ !in_array($context_id, $tree->getPathId($resource_link_ref_id), true)) {
+ throw ilLTIConsumerHttpException::notFound('Resource link not found');
+ }
+
+ $lti_object_id = ilObject::_lookupObjId($resource_link_ref_id);
+ if (!$lti_object_id) {
+ throw ilLTIConsumerHttpException::notFound('Resource link not found');
+ }
+
+ $this->checkToolMatchesObject($lti_object_id, $token);
+ $this->checkScore($request_data, $lti_object_id, $item_id);
}
- protected function checkScore(string $requestData, int $objId): int
+ protected function checkScore(string $requestData, int $objId, ?int $grade_item_id = null): void
{
global $DIC; /* @var \ILIAS\DI\Container $DIC */
@@ -87,118 +142,179 @@ protected function checkScore(string $requestData, int $objId): int
$logger->info('checkScore');
$score = json_decode($requestData);
- //prüfe Userid
- $userId = ilCmiXapiUser::getUsrIdForObjectAndUsrIdent($objId, $score->userId);
- if ($userId == null) {
- ilObjLTIConsumer::getLogger()->info('User not available');
- throw new Exception('User not available', 404);
- return 404;
- }
-
- ilObjLTIConsumer::getLogger()->dump($score);
-
- if (empty($score) ||
+ $activityProgress = is_object($score) && is_string($score->activityProgress ?? null)
+ ? ilLTIConsumerActivityProgress::tryFrom($score->activityProgress) : null;
+ $gradingProgress = is_object($score) && is_string($score->gradingProgress ?? null)
+ ? ilLTIConsumerGradingProgress::tryFrom($score->gradingProgress) : null;
+ if (!is_object($score) || json_last_error() !== JSON_ERROR_NONE ||
!isset($score->userId) ||
!isset($score->gradingProgress) ||
!isset($score->activityProgress) ||
!isset($score->timestamp) ||
- isset($score->timestamp) && !self::validate_iso8601_date($score->timestamp) ||
+ !is_scalar($score->userId) ||
+ !is_scalar($score->timestamp) ||
+ $activityProgress === null ||
+ $gradingProgress === null ||
+ !self::validate_iso8601_date((string) $score->timestamp) ||
(isset($score->scoreGiven) && !is_numeric($score->scoreGiven)) ||
(isset($score->scoreGiven) && !isset($score->scoreMaximum)) ||
- (isset($score->scoreMaximum) && !is_numeric($score->scoreMaximum))
+ (isset($score->scoreMaximum) && (!is_numeric($score->scoreMaximum) || (float) $score->scoreMaximum <= 0)) ||
+ (isset($score->scoreGiven) && (float) $score->scoreGiven < 0) ||
+ ($gradingProgress === ilLTIConsumerGradingProgress::FULLY_GRADED && (!isset($score->scoreGiven) || !isset($score->scoreMaximum)))
) {
ilObjLTIConsumer::getLogger()->info('Incorrect score received');
ilObjLTIConsumer::getLogger()->dump($score);
- throw new Exception('Incorrect score received', 400);
- return 400;
+ throw ilLTIConsumerHttpException::badRequest('Incorrect score received');
+ }
+
+ $userId = $this->resolveUserIdFromLtiIdent($objId, (string) $score->userId);
+ if ($userId == null) {
+ ilObjLTIConsumer::getLogger()->info('User not available');
+ throw ilLTIConsumerHttpException::notFound('User not available');
+ }
+
+ $lti_timestamp = DateTimeImmutable::createFromFormat(DateTimeInterface::RFC3339_EXTENDED, (string) $score->timestamp);
+ if (!$lti_timestamp) { //moodle 4
+ $lti_timestamp = DateTimeImmutable::createFromFormat(DateTimeInterface::ISO8601, (string) $score->timestamp);
}
+ if (!$lti_timestamp) { //for example nothing
+ $lti_timestamp = new DateTimeImmutable('now');
+ }
+
+ $grade_item_id_for_query = $grade_item_id ?? $objId;
+ $latest_grade_query = 'SELECT lti_timestamp FROM lti_consumer_grades'
+ . ' WHERE obj_id = ' . $DIC->database()->quote($grade_item_id_for_query, 'integer')
+ . ' AND usr_id = ' . $DIC->database()->quote($userId, 'integer')
+ . ' ORDER BY lti_timestamp DESC, stored DESC';
+ $latest_grade_result = $DIC->database()->query($latest_grade_query);
+ $latest_grade = $DIC->database()->fetchAssoc($latest_grade_result);
+ $is_current_score = $latest_grade === null ||
+ $lti_timestamp >= new DateTimeImmutable($latest_grade['lti_timestamp']);
+
+ $scoreGiven = isset($score->scoreGiven) ? (float) $score->scoreGiven : null;
+ $scoreMaximum = isset($score->scoreMaximum) ? (float) $score->scoreMaximum : null;
- if (!isset($score->scoreMaximum)) {
- $score->scoreMaximum = 1;
+ $result = null;
+ $scoreProgress = null;
+ if ($scoreGiven !== null && $scoreMaximum !== null) {
+ $scoreProgress = $scoreGiven / $scoreMaximum;
}
- if (!isset($score->scoreGiven)) {
- $score->scoreGiven = 0;
+ if ($gradingProgress === ilLTIConsumerGradingProgress::FULLY_GRADED) {
+ $result = $scoreProgress;
}
- $result = (float) $score->scoreGiven / (float) $score->scoreMaximum;
+ if ($grade_item_id !== null) {
+ $this->storeScore(
+ $grade_item_id,
+ $userId,
+ $scoreGiven,
+ $scoreMaximum,
+ $activityProgress,
+ $gradingProgress,
+ $lti_timestamp
+ );
+ return;
+ }
$ltiObjRes = new ilLTIConsumerResultService();
$ltiObjRes->readProperties($objId);
// check the object status
if (!$ltiObjRes->isAvailable()) {
- throw new Exception('Tool for Object not available', 404);
- return 404;
+ throw ilLTIConsumerHttpException::notFound('Tool for Object not available');
}
$lp_status = ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM;
+ $updateLpStatus = false;
- if ($score->activityProgress === 'InProgress') {
+ if ($activityProgress->isInProgress() ||
+ ($activityProgress === ilLTIConsumerActivityProgress::SUBMITTED && $gradingProgress->isPending())) {
$lp_status = ilLPStatus::LP_STATUS_IN_PROGRESS_NUM;
- } elseif ($score->activityProgress === 'Completed' && $score->gradingProgress === 'FullyGraded') {
- if ($result >= $ltiObjRes->getMasteryScore()) {
- $lp_status = ilLPStatus::LP_STATUS_COMPLETED_NUM;
+ $updateLpStatus = true;
+ } elseif ($activityProgress->isSubmittedOrCompleted()) {
+ if ($gradingProgress === ilLTIConsumerGradingProgress::FULLY_GRADED && $result !== null) {
+ if ($result >= $ltiObjRes->getMasteryScore()) {
+ $lp_status = ilLPStatus::LP_STATUS_COMPLETED_NUM;
+ } else {
+ $lp_status = ilLPStatus::LP_STATUS_IN_PROGRESS_NUM;
+ }
} else {
$lp_status = ilLPStatus::LP_STATUS_IN_PROGRESS_NUM;
}
- } elseif ($score->activityProgress === 'Completed' && $score->gradingProgress === 'Failed') {
- $lp_status = ilLPStatus::LP_STATUS_FAILED_NUM;
+ $updateLpStatus = true;
}
- $lp_percentage = (int) round(100 * $result);
+ $lp_percentage = $scoreProgress === null ? 0 : max(0, min(100, (int) round(100 * $scoreProgress)));
+ $resultForLog = $result === null ? 'null' : (string) $result;
- ilObjLTIConsumer::getLogger()->info("lp_status: $lp_status, lp_percentage: $lp_percentage, result: $result, mastery_score: " . $ltiObjRes->getMasteryScore());
+ ilObjLTIConsumer::getLogger()->info("lp_status: $lp_status, lp_percentage: $lp_percentage, result: $resultForLog, mastery_score: " . $ltiObjRes->getMasteryScore());
- $consRes = ilLTIConsumerResult::getByKeys($objId, $userId, false);
- if (empty($consRes)) {
- $DIC->database()->insert(
- 'lti_consumer_results',
- array(
- 'id' => array('integer', $DIC->database()->nextId('lti_consumer_results')),
- 'obj_id' => array('integer', $objId),
- 'usr_id' => array('integer', $userId),
- 'result' => array('float', $result)
- )
- );
- } else {
- $DIC->database()->replace(
- 'lti_consumer_results',
- array(
- 'id' => array('integer', $consRes->id)
- ),
- array(
- 'obj_id' => array('integer', $objId),
- 'usr_id' => array('integer', $userId),
- 'result' => array('float', $result)
- )
- );
+ $should_update_result = $result !== null || $scoreGiven === null;
+ if ($is_current_score && $should_update_result) {
+ $consRes = ilLTIConsumerResult::getByKeys($objId, $userId, false);
+ if (empty($consRes) && $result !== null) {
+ $DIC->database()->insert(
+ 'lti_consumer_results',
+ array(
+ 'id' => array('integer', $DIC->database()->nextId('lti_consumer_results')),
+ 'obj_id' => array('integer', $objId),
+ 'usr_id' => array('integer', $userId),
+ 'result' => array('float', $result)
+ )
+ );
+ } elseif (!empty($consRes)) {
+ $DIC->database()->replace(
+ 'lti_consumer_results',
+ array(
+ 'id' => array('integer', $consRes->id)
+ ),
+ array(
+ 'obj_id' => array('integer', $objId),
+ 'usr_id' => array('integer', $userId),
+ 'result' => array('float', $result)
+ )
+ );
+ }
}
- ilLPStatus::writeStatus($objId, $userId, $lp_status, $lp_percentage, true);
-
- $ltiTimestamp = DateTimeImmutable::createFromFormat(DateTimeInterface::RFC3339_EXTENDED, $score->timestamp);
- if (!$ltiTimestamp) { //moodle 4
- $ltiTimestamp = DateTimeImmutable::createFromFormat(DateTimeInterface::ISO8601, $score->timestamp);
- }
- if (!$ltiTimestamp) { //for example nothing
- $ltiTimestamp = new DateTime('now');
+ if ($is_current_score && $updateLpStatus) {
+ ilLPStatus::writeStatus($objId, $userId, $lp_status, $lp_percentage, true);
}
- $gradeValues = [
- 'id' => array('integer', $DIC->database()->nextId('lti_consumer_grades')),
- 'obj_id' => array('integer', $objId),
- 'usr_id' => array('integer', $userId),
- 'score_given' => array('float', $score->scoreGiven),
- 'score_maximum' => array('float', $score->scoreMaximum),
- 'activity_progress' => array('text', $score->activityProgress),
- 'grading_progress' => array('text', $score->gradingProgress),
- 'lti_timestamp' => array('timestamp',$ltiTimestamp->format("Y-m-d H:i:s")),
- 'stored' => array('timestamp', date("Y-m-d H:i:s"))
- ];
- $DIC->database()->insert('lti_consumer_grades', $gradeValues);
+ $this->storeScore(
+ $objId,
+ $userId,
+ $scoreGiven,
+ $scoreMaximum,
+ $activityProgress,
+ $gradingProgress,
+ $lti_timestamp
+ );
+ }
+ protected function storeScore(
+ int $item_id,
+ int $user_id,
+ ?float $score_given,
+ ?float $score_maximum,
+ ilLTIConsumerActivityProgress $activity_progress,
+ ilLTIConsumerGradingProgress $grading_progress,
+ DateTimeImmutable $lti_timestamp
+ ): void {
+ global $DIC;
- return 200;
+ $grade_values = [
+ 'id' => array('integer', $DIC->database()->nextId('lti_consumer_grades')),
+ 'obj_id' => array('integer', $item_id),
+ 'usr_id' => array('integer', $user_id),
+ 'score_given' => array('float', $score_given),
+ 'score_maximum' => array('float', $score_maximum),
+ 'activity_progress' => array('text', $activity_progress->value),
+ 'grading_progress' => array('text', $grading_progress->value),
+ 'lti_timestamp' => array('timestamp', $lti_timestamp->format('Y-m-d H:i:s')),
+ 'stored' => array('timestamp', date("Y-m-d H:i:s"))
+ ];
+ $DIC->database()->insert('lti_consumer_grades', $grade_values);
}
public static function validate_iso8601_date(string $date): bool
diff --git a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeSynchronization.php b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeSynchronization.php
index 8a186cfc6425..8ad90a7ed7e4 100755
--- a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeSynchronization.php
+++ b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeSynchronization.php
@@ -85,13 +85,19 @@ public static function getGradesForObject(int $objId, ?int $usrID = null, ?strin
$query .= ' AND lti_timestamp <= ' . $DIC->database()->quote($endDate->get(IL_CAL_DATETIME), 'timestamp');
}
- $query .= ' ORDER BY lti_timestamp DESC';
+ $query .= ' ORDER BY lti_timestamp DESC, stored DESC';
$res = $DIC->database()->query($query);
$results = [];
+ $seenUsers = [];
while ($row = $DIC->database()->fetchAssoc($res)) {
+ $userId = (int) $row['usr_id'];
+ if (isset($seenUsers[$userId])) {
+ continue;
+ }
+ $seenUsers[$userId] = true;
$results[] = $row;
}
diff --git a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeSynchronizationGUI.php b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeSynchronizationGUI.php
index 3590d4d8f042..0fbbb5ce4c4a 100755
--- a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeSynchronizationGUI.php
+++ b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeSynchronizationGUI.php
@@ -67,7 +67,7 @@ protected function showCmd(): void
$table = new ilLTIConsumerGradeSynchronizationTableGUI($isMultiActorReport);
$cUser = null;
- if (!$this->access->hasOutcomesAccess()) {
+ if (!$isMultiActorReport) {
$cUser = $DIC->user()->getId();
}
diff --git a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeSynchronizationTableGUI.php b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeSynchronizationTableGUI.php
index 5b31457117a2..e3c6c8b2c42f 100755
--- a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeSynchronizationTableGUI.php
+++ b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradeSynchronizationTableGUI.php
@@ -69,6 +69,7 @@ public function getRows(
$records = $this->applyOrdering($this->records, $order, $range);
foreach ($records as $record) {
$record['lti_timestamp'] = new DateTimeImmutable($record['lti_timestamp']);
+ $record['actor'] = ilObjUser::_lookupFullname((int) $record['usr_id']);
$record['score_given'] = $record['score_given'] . ' / ' . $record['score_maximum'];
$record['activity_progress'] = $this->lng->txt('grade_activity_progress_' . strtolower($record['activity_progress']));
$record['grading_progress'] = $this->lng->txt('grade_grading_progress_' . strtolower($record['grading_progress']));
diff --git a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradingProgress.php b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradingProgress.php
new file mode 100644
index 000000000000..871df18d0a44
--- /dev/null
+++ b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerGradingProgress.php
@@ -0,0 +1,17 @@
+id,
+ $this->contextId,
+ $this->clientId,
+ $label,
+ $scoreMaximum,
+ $resourceId,
+ $resourceLinkId,
+ $tag
+ );
+ }
+}
diff --git a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerLineItemRepository.php b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerLineItemRepository.php
new file mode 100644
index 000000000000..514c0b3615e1
--- /dev/null
+++ b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerLineItemRepository.php
@@ -0,0 +1,114 @@
+ */
+ public function getForContextAndClient(int $contextId, string $clientId): array
+ {
+ $result = $this->db->query(
+ 'SELECT * FROM lti_consumer_lineitems'
+ . ' WHERE context_id = ' . $this->db->quote($contextId, 'integer')
+ . ' AND client_id = ' . $this->db->quote($clientId, 'text')
+ . ' AND enabled = ' . $this->db->quote(1, 'integer')
+ );
+
+ $lineItems = [];
+ while ($row = $this->db->fetchAssoc($result)) {
+ $lineItems[] = $this->fromRow($row);
+ }
+ return $lineItems;
+ }
+
+ public function get(int $id, int $contextId, string $clientId): ?ilLTIConsumerLineItem
+ {
+ $result = $this->db->query(
+ 'SELECT * FROM lti_consumer_lineitems'
+ . ' WHERE id = ' . $this->db->quote($id, 'integer')
+ . ' AND context_id = ' . $this->db->quote($contextId, 'integer')
+ . ' AND client_id = ' . $this->db->quote($clientId, 'text')
+ . ' AND enabled = ' . $this->db->quote(1, 'integer')
+ );
+ $row = $this->db->fetchAssoc($result);
+
+ return $row ? $this->fromRow($row) : null;
+ }
+
+ public function create(
+ int $contextId,
+ string $clientId,
+ ?string $label,
+ float $scoreMaximum,
+ string $resourceId,
+ string $resourceLinkId,
+ string $tag
+ ): ilLTIConsumerLineItem {
+ $id = $this->db->nextId('lti_consumer_lineitems');
+ $lineItem = new ilLTIConsumerLineItem(
+ $id,
+ $contextId,
+ $clientId,
+ $label ?? 'Line Item ' . $id,
+ $scoreMaximum,
+ $resourceId,
+ $resourceLinkId,
+ $tag
+ );
+ $this->db->insert('lti_consumer_lineitems', [
+ 'id' => ['integer', $lineItem->id],
+ 'context_id' => ['integer', $lineItem->contextId],
+ 'obj_id' => ['integer', null],
+ 'client_id' => ['text', $lineItem->clientId],
+ 'label' => ['text', $lineItem->label],
+ 'score_maximum' => ['float', $lineItem->scoreMaximum],
+ 'resource_id' => ['text', $lineItem->resourceId],
+ 'resource_link_id' => ['text', $lineItem->resourceLinkId],
+ 'tag' => ['text', $lineItem->tag],
+ 'enabled' => ['integer', 1]
+ ]);
+
+ return $lineItem;
+ }
+
+ public function update(ilLTIConsumerLineItem $lineItem): void
+ {
+ $this->db->update('lti_consumer_lineitems', [
+ 'label' => ['text', $lineItem->label],
+ 'score_maximum' => ['float', $lineItem->scoreMaximum],
+ 'resource_id' => ['text', $lineItem->resourceId],
+ 'resource_link_id' => ['text', $lineItem->resourceLinkId],
+ 'tag' => ['text', $lineItem->tag]
+ ], [
+ 'id' => ['integer', $lineItem->id]
+ ]);
+ }
+
+ public function disable(ilLTIConsumerLineItem $lineItem): void
+ {
+ $this->db->update('lti_consumer_lineitems', [
+ 'enabled' => ['integer', 0]
+ ], [
+ 'id' => ['integer', $lineItem->id]
+ ]);
+ }
+
+ /** @param array $row */
+ private function fromRow(array $row): ilLTIConsumerLineItem
+ {
+ return new ilLTIConsumerLineItem(
+ (int) $row['id'],
+ (int) $row['context_id'],
+ (string) ($row['client_id'] ?? ''),
+ (string) ($row['label'] ?? ''),
+ (float) ($row['score_maximum'] ?? 1),
+ (string) ($row['resource_id'] ?? ''),
+ (string) ($row['resource_link_id'] ?? ''),
+ (string) ($row['tag'] ?? '')
+ );
+ }
+}
diff --git a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerResourceBase.php b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerResourceBase.php
index 8830d7dbf01c..ec0ce5a83f48 100755
--- a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerResourceBase.php
+++ b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerResourceBase.php
@@ -144,13 +144,86 @@ protected function parseTemplate(): array
/**
* Check to make sure the request is valid.
*/
- public function checkTool(array $scopes = array()): ?object
+ /** @param list $scopes */
+ public function checkTool(array $scopes = array()): ?ilLTIConsumerAccessToken
{
$token = $this->getService()->checkTool();
$permittedScopes = $this->getService()->getPermittedScopes();
- if (empty($scopes) || empty(array_intersect($permittedScopes, $scopes))) {
- $token = null;
+
+ if ($token === null || empty($scopes) || empty(array_intersect($permittedScopes, $scopes))) {
+ return null;
+ }
+
+ if (empty(array_intersect($token->getScopes(), $scopes))) {
+ return null;
}
+
return $token;
}
+
+ protected function resolveUserIdFromLtiIdent(int $objId, string $userIdent): ?int
+ {
+ global $DIC;
+ $ilDB = $DIC->database();
+
+ $query = 'SELECT usr_id FROM cmix_users'
+ . ' WHERE obj_id = ' . $ilDB->quote($objId, 'integer')
+ . ' AND usr_ident = ' . $ilDB->quote($userIdent, 'text');
+ $res = $ilDB->query($query);
+ $row = $ilDB->fetchAssoc($res);
+ if ($row) {
+ return (int) $row['usr_id'];
+ }
+
+ $userId = ilCmiXapiUser::getUsrIdForObjectAndUsrIdent($objId, $userIdent);
+ if ($userId !== null) {
+ return $userId;
+ }
+
+ $query = 'SELECT usr_id, privacy_ident FROM cmix_users'
+ . ' WHERE obj_id = ' . $ilDB->quote($objId, 'integer');
+ $res = $ilDB->query($query);
+ while ($row = $ilDB->fetchAssoc($res)) {
+ $user = new ilObjUser((int) $row['usr_id']);
+ if (ilCmiXapiUser::getIdentAsId((int) $row['privacy_ident'], $user) === $userIdent) {
+ return (int) $row['usr_id'];
+ }
+ }
+
+ return null;
+ }
+
+ protected function matchesLtiUserIdent(int $objId, int $userId, string $userIdent, string $filter): bool
+ {
+ foreach ($this->getLtiUserIdentCandidates($objId, $userId, $userIdent) as $candidate) {
+ if ($candidate === $filter) {
+ return true;
+ }
+
+ if (strpos($filter, '@') === false && str_starts_with($candidate, $filter . '@')) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ protected function getLtiUserIdentCandidates(int $objId, int $userId, string $userIdent): array
+ {
+ global $DIC;
+ $ilDB = $DIC->database();
+
+ $idents = [$userIdent, (string) $userId];
+ $query = 'SELECT usr_ident, privacy_ident FROM cmix_users'
+ . ' WHERE obj_id = ' . $ilDB->quote($objId, 'integer')
+ . ' AND usr_id = ' . $ilDB->quote($userId, 'integer');
+ $res = $ilDB->query($query);
+ $user = new ilObjUser($userId);
+ while ($row = $ilDB->fetchAssoc($res)) {
+ $idents[] = (string) $row['usr_ident'];
+ $idents[] = ilCmiXapiUser::getIdentAsId((int) $row['privacy_ident'], $user);
+ }
+
+ return array_values(array_unique(array_filter($idents, static fn($ident): bool => $ident !== '')));
+ }
}
diff --git a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerResult.php b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerResult.php
index 2fcb38d7105b..aed77231c376 100755
--- a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerResult.php
+++ b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerResult.php
@@ -175,11 +175,6 @@ public function getResult(): ?float
return $this->result;
}
- public function isAttended(): bool
- {
- return $this->attended;
- }
-
public function setAttended(bool $attended): void
{
$this->attended = $attended;
diff --git a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerServiceBase.php b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerServiceBase.php
index 07088e085121..f72c561b25a3 100755
--- a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerServiceBase.php
+++ b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerServiceBase.php
@@ -115,9 +115,10 @@ public function getResourcePath(): string
/**
* Check that the request has been properly signed and is permitted.
*/
- public function checkTool(): ?object
+ public function checkTool(): ?ilLTIConsumerAccessToken
{
- return ilObjLTIConsumer::verifyToken();
+ $token = ilObjLTIConsumer::verifyToken();
+ return $token === null ? null : ilLTIConsumerAccessToken::fromVerifiedToken($token);
}
/**
diff --git a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerServiceResponse.php b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerServiceResponse.php
index c59f95f98661..c843fd0f95ae 100755
--- a/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerServiceResponse.php
+++ b/components/ILIAS/LTIConsumer/classes/class.ilLTIConsumerServiceResponse.php
@@ -195,14 +195,12 @@ public function setBody(string $body): void
$this->body = $body;
}
- /**
- * Add an additional header.
- */
- /*
- public function add_additional_header(string $header): void {
+ /** Add an additional header. */
+ public function addAdditionalHeader(string $header): void
+ {
$this->additionalheaders[] = $header;
}
- */
+
/**
* Send the response.
*/
diff --git a/components/ILIAS/LTIConsumer/classes/class.ilObjLTIConsumer.php b/components/ILIAS/LTIConsumer/classes/class.ilObjLTIConsumer.php
index d1de59c612d3..1f08341caea3 100755
--- a/components/ILIAS/LTIConsumer/classes/class.ilObjLTIConsumer.php
+++ b/components/ILIAS/LTIConsumer/classes/class.ilObjLTIConsumer.php
@@ -66,6 +66,8 @@ class ilObjLTIConsumer extends ilObject2
protected string $customParams = '';
+ protected float $scoreMaximum = 1.0;
+
protected ?int $ref_id = 0;
//Highscore
@@ -106,7 +108,7 @@ public function __construct(int $a_id = 0, bool $a_reference = true)
parent::__construct($a_id, $a_reference);
}
- public static function getRefIdOfConsumerByDeploymentId(string $dep_id): int
+ public static function getRefIdOfConsumerByDeploymentId(string $dep_id): int|null
{
global $ilDB;
$refId = null;
@@ -189,6 +191,16 @@ public function setMasteryScorePercent(float $mastery_score_percent): void
$this->mastery_score = $mastery_score_percent / 100;
}
+ public function getScoreMaximum(): float
+ {
+ return $this->scoreMaximum;
+ }
+
+ public function setScoreMaximum(float $scoreMaximum): void
+ {
+ $this->scoreMaximum = $scoreMaximum;
+ }
+
public function getProviderId(): int
{
return $this->providerId;
@@ -404,6 +416,9 @@ public function load(): void
$this->setHighscoreTopNum((int) $row['highscore_top_num']);
$this->setMasteryScore((float) $row['mastery_score']);
+ if (isset($row['score_maximum'])) {
+ $this->setScoreMaximum((float) $row['score_maximum']);
+ }
}
$this->loadRepositoryActivationSettings();
@@ -437,7 +452,8 @@ public function save(): void
'highscore_own_table' => ['integer', (int) $this->getHighscoreOwnTable()],
'highscore_top_table' => ['integer', (int) $this->getHighscoreTopTable()],
'highscore_top_num' => ['integer', $this->getHighscoreTopNum()],
- 'mastery_score' => ['float', $this->getMasteryScore()]
+ 'mastery_score' => ['float', $this->getMasteryScore()],
+ 'score_maximum' => ['float', $this->getScoreMaximum()]
]);
$this->saveRepositoryActivationSettings();
@@ -869,9 +885,11 @@ public function buildLaunchParametersLTI13(
break;
}
- $userIdLTI = ilCmiXapiUser::getIdentAsId($this->getProvider()->getPrivacyIdent(), $DIC->user());
-
$emailPrimary = $cmixUser->getUsrIdent();
+ $userIdLTI = ilCmiXapiUser::getIdentAsId($this->getProvider()->getPrivacyIdent(), $DIC->user());
+ if ($this->getProvider()->getPrivacyIdent() == ilObjCmiXapi::PRIVACY_IDENT_IL_UUID_RANDOM) {
+ $userIdLTI = strstr($emailPrimary, '@' . ilCmiXapiUser::getIliasUuid(), true);
+ }
ilLTIConsumerResult::getByKeys($this->getId(), $DIC->user()->getId(), true);
@@ -927,16 +945,30 @@ public function buildLaunchParametersLTI13(
if ($this->getProvider()->isGradeSynchronization() || $this->getProvider()->getHasOutcome()) {
$gradeservice = new ilLTIConsumerGradeService();
- $launch_vars['custom_lineitem_url'] = self::getIliasHttpPath(
- ) . "/ltiservices.php/gradeservice/" . $contextId . "/lineitems/" . $this->id . "/lineitem";
+ // the launch claim and the id the tool reads back from the service must be
+ // identical (AGS 2.0 §3.3.4.3), so both go through the same builder
+ $lineitemUrl = ilLTIConsumerGradeServiceLineItem::buildLineItemUrl((int) $contextId, (int) $this->id);
+ $lineitemsUrl = ilLTIConsumerGradeServiceLineItem::buildLineItemsUrl((int) $contextId);
+
+ $launch_vars['custom_lineitem_url'] = $lineitemUrl;
// ! Moodle as tool provider requires a custom_lineitems_url even though this should be optional in launch request, especially if only posting score scope is permitted by platform
// http://www.imsglobal.org/spec/lti-ags/v2p0#example-link-has-a-single-line-item-tool-can-only-post-score
- $launch_vars['custom_lineitems_url'] = self::getIliasHttpPath()
- . "/ltiservices.php/gradeservice/" . $contextId . "/lineitems/";
+ $launch_vars['custom_lineitems_url'] = $lineitemsUrl;
$launch_vars['custom_ags_scopes'] = implode(",", $gradeservice->getPermittedScopes());
+
+ if ($additionalArguments === null) {
+ $additionalArguments = [];
+ }
+ if (!isset($additionalArguments[self::LTI_JWT_CLAIM_PREFIX . '/claim/message_type'])) {
+ $additionalArguments['https://purl.imsglobal.org/spec/lti-ags/claim/endpoint'] = [
+ 'scope' => $gradeservice->getPermittedScopes(),
+ 'lineitems' => $lineitemsUrl,
+ 'lineitem' => $lineitemUrl
+ ];
+ }
}
if (!empty(self::verifyPrivateKey())) {
@@ -998,8 +1030,8 @@ public static function buildContentSelectionParameters(
break;
}
- $userIdLTI = ilCmiXapiUser::getIdentAsId($provider->getPrivacyIdent(), $DIC->user());
- $emailPrimary = ilCmiXapiUser::getIdent($provider->getPrivacyIdent(), $DIC->user());
+ $userIdLTI = self::getDeepLinkingUserIdentifier($provider, $DIC->user());
+ $emailPrimary = self::getDeepLinkingUserEmail($provider, $DIC->user());
$toolConsumerInstanceGuid = CLIENT_ID . ".";
$parseIliasUrl = parse_url(self::getIliasHttpPath());
if (array_key_exists("path", $parseIliasUrl)) {
@@ -1052,7 +1084,17 @@ public static function buildContentSelectionParameters(
$DIC->ui()->mainTemplate()->setOnScreenMessage('failure', 'ERROR_OPEN_SSL_CONF', true);
return null;
}
- return self::LTISignJWT($content_select_vars, '', $clientId, $deploymentId, $nonce);
+ return self::LTISignJWT($content_select_vars, $provider->getContentItemUrl(), $clientId, $deploymentId, $nonce);
+ }
+
+ public static function getDeepLinkingUserIdentifier(ilLTIConsumeProvider $provider, ilObjUser $user): string
+ {
+ return ilCmiXapiUser::getIdentAsId($provider->getPrivacyIdent(), $user);
+ }
+
+ public static function getDeepLinkingUserEmail(ilLTIConsumeProvider $provider, ilObjUser $user): string
+ {
+ return ilCmiXapiUser::getIdent($provider->getPrivacyIdent(), $user);
}
public static function LTISignJWT(
@@ -1382,6 +1424,9 @@ public static function registerClient(array $data, object $tokenObj): array
$provider->setContentItemUrl($message['target_link_uri']);
}
}
+ if (self::registrationRequestsAgs($data, $toolConfig)) {
+ $provider->setGradeSynchronization(true);
+ }
/*
if (isset($data['logo_uri'])) { // needs to be uploaded and then assign filepath
$provider->setProviderIconFilename($data['logo_uri']);
@@ -1399,6 +1444,42 @@ public static function registerClient(array $data, object $tokenObj): array
return $reponseData;
}
+ private static function registrationRequestsAgs(array $data, array $toolConfig): bool
+ {
+ $requestedScopes = [];
+ foreach ([$data['scope'] ?? null, $data['scopes'] ?? null] as $scopeValue) {
+ $requestedScopes = array_merge($requestedScopes, self::normalizeRegistrationScopes($scopeValue));
+ }
+
+ if (isset($toolConfig['services']) && is_array($toolConfig['services'])) {
+ foreach ($toolConfig['services'] as $service) {
+ if (!is_array($service)) {
+ continue;
+ }
+ $requestedScopes = array_merge(
+ $requestedScopes,
+ self::normalizeRegistrationScopes($service['scope'] ?? null),
+ self::normalizeRegistrationScopes($service['scopes'] ?? null)
+ );
+ }
+ }
+
+ $requestedScopes = array_unique($requestedScopes);
+ $agsScopes = (new ilLTIConsumerGradeService())->getPermittedScopes();
+ return !empty(array_intersect($requestedScopes, $agsScopes));
+ }
+
+ private static function normalizeRegistrationScopes(mixed $scopeValue): array
+ {
+ if (is_string($scopeValue)) {
+ return preg_split('/\s+/', trim($scopeValue)) ?: [];
+ }
+ if (is_array($scopeValue)) {
+ return array_values(array_filter($scopeValue, static fn($scope): bool => is_string($scope) && $scope !== ''));
+ }
+ return [];
+ }
+
public static function getNewClientId(): string
{
return Util::getRandomString(15);
diff --git a/components/ILIAS/LTIConsumer/classes/class.ilObjLTIConsumerGUI.php b/components/ILIAS/LTIConsumer/classes/class.ilObjLTIConsumerGUI.php
index ac8e56c23ed9..984efbb7262d 100755
--- a/components/ILIAS/LTIConsumer/classes/class.ilObjLTIConsumerGUI.php
+++ b/components/ILIAS/LTIConsumer/classes/class.ilObjLTIConsumerGUI.php
@@ -37,6 +37,7 @@
* @ilCtrl_Calls ilObjLTIConsumerGUI: ilLTIConsumerScoringGUI
* @ilCtrl_Calls ilObjLTIConsumerGUI: ilLTIConsumerContentGUI
* @ilCtrl_Calls ilObjLTIConsumerGUI: ilLTIConsumerGradeSynchronizationGUI
+ * @ilCtrl_Calls ilObjLTIConsumerGUI: ilLTIConsumeProviderSettingsGUI
*/
class ilObjLTIConsumerGUI extends ilObject2GUI
{
@@ -171,7 +172,7 @@ public function initDynRegForm(string $a_new_type): \ilLTIConsumeProviderFormGUI
/* @var \ILIAS\DI\Container $DIC */
$provider = new ilLTIConsumeProvider();
$form = new ilLTIConsumeProviderFormGUI($provider);
- $form->initDynRegForm($this->ctrl->getFormAction($this, "cancelDynReg"));
+ $form->initDynRegForm($this->ctrl->getFormAction($this, "addDynReg"));
$form->setTitle($DIC->language()->txt($a_new_type . '_dynamic_registration'));
return $form;
}
@@ -379,9 +380,7 @@ public function saveDynReg(): void
public function contentSelection(string $providerId, string $newType, string $refId, ilLTIConsumeProvider $provider): void
{
global $DIC;
- if (!ilLTIConsumerAccess::hasCustomProviderCreationAccess()) {
- throw new ilLtiConsumerException('permission denied!');
- }
+ $this->checkContentSelectionAccess($refId);
$DIC->ctrl()->setParameter($this, "new_type", $newType);
$DIC->ctrl()->setParameter($this, "provider_id", $providerId);
$DIC->ctrl()->setParameter($this, "ref_id", $refId);
@@ -394,39 +393,53 @@ public function contentSelection(string $providerId, string $newType, string $re
public function contentSelectionRequest(): void
{
global $DIC;
- if (!ilLTIConsumerAccess::hasCustomProviderCreationAccess()) {
- throw new ilLtiConsumerException('permission denied!');
- }
$new_type = $this->getRequestValue("new_type");
$DIC->ctrl()->setParameter($this, "new_type", $new_type);
$provider_id = $this->getRequestValue("provider_id");
$DIC->ctrl()->setParameter($this, "provider_id", $provider_id);
$ref_id = $this->getRequestValue("ref_id");
$DIC->ctrl()->setParameter($this, "ref_id", $ref_id);
+ $this->checkContentSelectionAccess($ref_id);
$DIC->language()->loadLanguageModule($new_type);
$provider = new ilLTIConsumeProvider((int) $provider_id);
$redirectUrl = $DIC->ctrl()->getLinkTarget($this, 'contentSelectionRequest');
if (!ilSession::has('lti13_login_data')) {
- $userIdLTI = ilCmiXapiUser::getIdentAsId($provider->getPrivacyIdent(), $DIC->user());
+ $state = bin2hex(random_bytes(32));
+ ilSession::set('lti13_deep_linking_state', [
+ 'state' => $state,
+ 'provider_id' => $provider->getId(),
+ 'ref_id' => (int) $ref_id,
+ 'flow' => 'content_selection',
+ 'created_at' => time()
+ ]);
+ $userIdLTI = ilObjLTIConsumer::getDeepLinkingUserIdentifier($provider, $DIC->user());
//$emailPrimary = ilCmiXapiUser::getIdent($provider->getPrivacyIdent(), $DIC->user());
$ltiMessageHint = (string) $ref_id . ":" . CLIENT_ID . ":" . base64_encode($redirectUrl);
$tplLogin = new ilTemplate("tpl.lti_initial_login.html", true, true, "components/ILIAS/LTIConsumer");
$tplLogin->setVariable("LTI_INITIAL_LOGIN_ACTION", $provider->getInitiateLogin());
$tplLogin->setVariable("ISS", ilObjLTIConsumer::getIliasHttpPath());
- $tplLogin->setVariable("TARGET_LINK_URL", $provider->getProviderUrl());
+ $tplLogin->setVariable("TARGET_LINK_URL", $provider->getContentItemUrl());
$tplLogin->setVariable("LOGIN_HINT", $userIdLTI);
$tplLogin->setVariable("LTI_MESSAGE_HINT", $ltiMessageHint);
$tplLogin->setVariable("CLIENT_ID", $provider->getClientId());
$tplLogin->setVariable("LTI_DEPLOYMENT_ID", (string) $provider->getId());
+ $tplLogin->setVariable("STATE", $state);
echo $tplLogin->get();
exit; //TODO: no exit
} else {
$loginData = ilSession::get('lti13_login_data');
+ $redirectUri = $loginData['redirect_uri'] ?? '';
+ $allowedRedirectUris = array_map('trim', explode(',', $provider->getRedirectionUris()));
+ if (!in_array($redirectUri, $allowedRedirectUris, true)) {
+ $DIC->http()->saveResponse($DIC->http()->response()->withStatus(400));
+ $DIC->http()->sendResponse();
+ $DIC->http()->close();
+ }
// ToDo: correct Link!! replace ILIAS_HTTP_PATH
$data = ilObjLTIConsumer::buildContentSelectionParameters($provider, (int) $ref_id, ilObjLTIConsumer::getIliasHttpPath() . "/" . $DIC->ctrl()->getLinkTarget($this, 'contentSelectionResponse'), $loginData['nonce']);
$tplContentSelection = new ilTemplate("tpl.lti_jwt_autosubmit.html", true, true, "components/ILIAS/LTIConsumer");
- $tplContentSelection->setVariable("LTI_JWT_FORM_ACTION", $provider->getContentItemUrl());
+ $tplContentSelection->setVariable("LTI_JWT_FORM_ACTION", $redirectUri);
$tplContentSelection->setVariable("LTI_JWT_ID_TOKEN", $data['id_token']);
$tplContentSelection->setVariable("LTI_JWT_STATE", $loginData['state']);
ilSession::clear('lti13_login_data');
@@ -438,15 +451,13 @@ public function contentSelectionRequest(): void
public function contentSelectionResponse(): void
{
global $DIC;
- if (!ilLTIConsumerAccess::hasCustomProviderCreationAccess()) {
- throw new ilLtiConsumerException('permission denied!');
- }
$new_type = $this->getRequestValue("new_type");
$DIC->ctrl()->setParameter($this, "new_type", $new_type);
$provider_id = $this->getRequestValue("provider_id");
$DIC->ctrl()->setParameter($this, "provider_id", $provider_id);
$ref_id = $this->getRequestValue("ref_id");
$DIC->ctrl()->setParameter($this, "ref_id", $ref_id);
+ $this->checkContentSelectionAccess($ref_id);
$DIC->language()->loadLanguageModule($new_type);
$token = '';
if ($DIC->http()->wrapper()->post()->has('JWT')) {
@@ -468,14 +479,19 @@ public function contentSelectionResponse(): void
public function cancelContentSelection(): void
{
global $DIC;
- if (!ilLTIConsumerAccess::hasCustomProviderCreationAccess()) {
- throw new ilLtiConsumerException('permission denied!');
- }
+ $this->checkContentSelectionAccess($this->getRequestValue("ref_id"));
$new_type = $this->getRequestValue("new_type");
$DIC->ctrl()->setParameterByClass(ilRepositoryGUI::class, 'new_type', $new_type);
$DIC->ctrl()->redirectByClass(ilRepositoryGUI::class, 'create');
}
+ protected function checkContentSelectionAccess(?string $refId): void
+ {
+ if ($refId === null || !$this->checkPermissionBool('create', '', 'lti', (int) $refId)) {
+ throw new ilLtiConsumerException('permission denied!');
+ }
+ }
+
public function saveContentSelection(ilLTIConsumeProvider $provider, string $token): void
{
if ($provider->getKeyType() == 'RSA_KEY') {
@@ -507,8 +523,13 @@ public function saveContentSelection(ilLTIConsumeProvider $provider, string $tok
$newObj->setProvider($provider);
// custom params
$customParams = [];
- foreach ($item->{'custom'} as $key => $value) {
- $customParams[] = $key . "=" . $value;
+ if (isset($item->url)) {
+ $customParams[] = 'target_link_uri=' . (string) $item->url;
+ }
+ if (isset($item->custom) && is_object($item->custom)) {
+ foreach ($item->custom as $key => $value) {
+ $customParams[] = $key . "=" . $value;
+ }
}
if (count($customParams) > 0) {
$newObj->setCustomParams(implode(";", $customParams));
@@ -697,11 +718,19 @@ public static function _goto(string $a_target): void
public function executeCommand(): void
{
global $DIC;
+
+ if ($DIC->ctrl()->getCmd() === 'startDeepLinking' && $this->object instanceof ilObjLTIAdministration) {
+ $DIC->ui()->mainTemplate()->setContent(
+ $this->ui_renderer->render($this->ui_factory->messageBox()->info($DIC->language()->txt('lti_deep_linking_not_available_for_admin_objects')))
+ );
+ return;
+ }
+
/* @var \ILIAS\DI\Container $DIC */
// TODO: general access checks (!)
if (!ilLTIConsumerContentGUI::isEmbeddedLaunchRequest()) {
$this->prepareOutput();
- $this->addHeaderAction();
+ //$this->addHeaderAction();
}
if (!$this->creation_mode) {
@@ -724,6 +753,11 @@ public function executeCommand(): void
$obj = $this->object;
switch ($DIC->ctrl()->getNextClass()) {
+ case strtolower(ilLTIConsumeProviderSettingsGUI::class):
+ $gui = new ilLTIConsumeProviderSettingsGUI($obj, $this->ltiAccess);
+ $this->ctrl->forwardCommand($gui);
+ break;
+
case strtolower(ilObjectCopyGUI::class):
$gui = new ilObjectCopyGUI($this);
@@ -826,6 +860,10 @@ public function executeCommand(): void
$DIC->ctrl()->redirectToURL($this->ctrl->getLinkTargetByClass(ilInfoScreenGUI::class));
}
$command = $DIC->ctrl()->getCmd(self::DEFAULT_CMD);
+ if (!$this->object instanceof ilObjLTIConsumer && $command === self::DEFAULT_CMD) {
+ $DIC->ctrl()->setParameterByClass(ilRepositoryGUI::class, 'new_type', $this->getType());
+ $DIC->ctrl()->redirectByClass(ilRepositoryGUI::class, 'create');
+ }
$this->{$command}();
}
}
@@ -1028,7 +1066,7 @@ protected function trackObjectReadEvent(): void
$this->object->getId(),
$DIC->user()->getId()
);
-
+ // dump("ilObjLTIConsumerGUI", $this->object, $this->object->getId(), $DIC->user()->getId());exit();
ilLPStatusWrapper::_updateStatus($this->object->getId(), $DIC->user()->getId());
}
diff --git a/components/ILIAS/LTIConsumer/resources/ltiauth.php b/components/ILIAS/LTIConsumer/resources/ltiauth.php
index 01f128ccd392..67b5fcd206af 100644
--- a/components/ILIAS/LTIConsumer/resources/ltiauth.php
+++ b/components/ILIAS/LTIConsumer/resources/ltiauth.php
@@ -82,28 +82,83 @@ function sanitizeJson(string $string)
$provider = ilLTIConsumeProvider::getInstance($provider_id);
$hint = sanitizeJson($ltiMessageHint);
- if ($provider->getContentItemUrl() == $redirectUri && isset($hint['deployment_id'])) {
+ $expectedState = ilSession::get('lti13_deep_linking_state');
+ $allowedRedirectUris = array_map('trim', explode(',', $provider->getRedirectionUris()));
+ if (
+ is_array($hint) &&
+ isset($hint['deployment_id']) &&
+ is_array($expectedState) &&
+ ($expectedState['flow'] ?? '') === 'content_selection' &&
+ is_string($expectedState['state'] ?? null) &&
+ is_int($expectedState['created_at'] ?? null) &&
+ $expectedState['created_at'] >= time() - 300 &&
+ $expectedState['created_at'] <= time() &&
+ is_string($state) &&
+ hash_equals($expectedState['state'], $state) &&
+ ($expectedState['provider_id'] ?? 0) === $provider->getId() &&
+ (int) $hint['deployment_id'] === $provider->getId() &&
+ in_array($redirectUri, $allowedRedirectUris, true)
+ ) {
- $isDlMode = true;
$deploymentId = (int) $hint['deployment_id'];
- $ownerId = ilObjectFactory::getInstanceByRefId(224)->getOwner();
$childRefId = ilObjLTIConsumer::getRefIdOfConsumerByDeploymentId((string) $deploymentId);
- $refId = $DIC->repositoryTree()->getParentId($childRefId);
+ if ($childRefId !== null) {
+ $refId = $DIC->repositoryTree()->getParentId($childRefId);
+ }
+ if ($refId > 0 && ($expectedState['ref_id'] ?? 0) === $refId) {
+ $isDlMode = true;
+ ilSession::clear('lti13_deep_linking_state');
+ }
}
}
-if (empty($ltiMessageHint)) {
+if (empty($ltiMessageHint) || (is_array($hint) && !$isDlMode)) {
$DIC->http()->saveResponse(
$DIC->http()->response()->withStatus(400)
);
$DIC->http()->sendResponse();
$DIC->http()->close();
- exit;
}
-$parts = explode(":", $ltiMessageHint);
+if ($isDlMode) {
+ if ($refId <= 0) {
+ $DIC->http()->saveResponse(
+ $DIC->http()->response()->withStatus(400)
+ );
+ $DIC->http()->sendResponse();
+ $DIC->http()->close();
+ }
+
+ ilSession::set('lti13_login_data', $data);
+
+ $DIC->ctrl()->setParameterByClass(ilObjLTIConsumerGUI::class, 'new_type', 'lti');
+ $DIC->ctrl()->setParameterByClass(ilObjLTIConsumerGUI::class, 'provider_id', (string) $deploymentId);
+ $DIC->ctrl()->setParameterByClass(ilObjLTIConsumerGUI::class, 'ref_id', (string) $refId);
+ $url = $DIC->ctrl()->getLinkTargetByClass([ilRepositoryGUI::class, ilObjLTIConsumerGUI::class], 'contentSelectionRequest');
+
+ $response = $DIC->http()->response()
+ ->withStatus(302)
+ ->withAddedHeader('Location', $url);
+
+ $sessionCookieHeader = buildSameSiteNoneSessionCookieHeader();
+ if ($sessionCookieHeader !== null) {
+ $response = $response->withAddedHeader('Set-Cookie', $sessionCookieHeader);
+ }
+
+ $DIC->http()->saveResponse($response);
+
+ try {
+ $DIC->http()->sendResponse();
+ $DIC->http()->close();
+ } catch (\ILIAS\HTTP\Response\Sender\ResponseSendingException $e) {
+ $DIC->http()->close();
+ }
+
+}
+
+$parts = explode(":", $ltiMessageHint, 3);
$isContentSelection = false;
$ref_id = '';
$il_client_id = '';
@@ -111,22 +166,37 @@ function sanitizeJson(string $string)
if (count($parts) === 2) {
[$ref_id, $il_client_id] = $parts;
} elseif (count($parts) === 3) {
- [$first, $second, $third] = $parts;
- $il_client_id = $third;
- $ref_id = explode(",", $second)[0];
-} else {
$isContentSelection = true;
[$ref_id, $il_client_id, $redirect_uri] = $parts;
+} else {
+ $DIC->http()->saveResponse(
+ $DIC->http()->response()->withStatus(400)
+ );
+ $DIC->http()->sendResponse();
+ $DIC->http()->close();
}
-ilSession::set('lti13_login_data', $data);
-
if ($isContentSelection) {
- $url = "../../../" . base64_decode($redirect_uri);
+ $redirect_target = base64_decode($redirect_uri, true);
+ if ($redirect_target === false || $redirect_target === '' ||
+ str_starts_with($redirect_target, '/') || str_contains($redirect_target, '..') ||
+ parse_url($redirect_target, PHP_URL_SCHEME) !== null ||
+ parse_url($redirect_target, PHP_URL_HOST) !== null) {
+ $DIC->http()->saveResponse(
+ $DIC->http()->response()->withStatus(400)
+ );
+ $DIC->http()->sendResponse();
+ $DIC->http()->close();
+ }
+ $url = "../../../" . $redirect_target;
} else {
$url = "../../../goto.php?target=lti_" . $ref_id . "&client_id=" . $il_client_id;
}
+// only persist the login data once the request has fully passed validation,
+// so a rejected request never leaves unvalidated data behind in the session
+ilSession::set('lti13_login_data', $data);
+
function buildSameSiteNoneSessionCookieHeader(): ?string
{
if (session_status() !== PHP_SESSION_ACTIVE || session_id() === '') {
diff --git a/components/ILIAS/LTIConsumer/resources/ltiregstart.php b/components/ILIAS/LTIConsumer/resources/ltiregstart.php
index e7cd895880ce..0f891ccb0492 100644
--- a/components/ILIAS/LTIConsumer/resources/ltiregstart.php
+++ b/components/ILIAS/LTIConsumer/resources/ltiregstart.php
@@ -71,7 +71,10 @@
ilSession::set('lti_dynamic_registration_custom_params', $customParams);
}
ilSession::set('lti_dynamic_registration_client_id', $clientId);
- header("Location: " . $url . "&openid_configuration=" . urlencode(ilObjLTIConsumer::getOpenidConfigUrl()) . "®istration_token=" . $regToken);
+ // a tool registration URL usually carries no query string of its own, so the
+ // parameters must start with "?" in that case or they end up in the path
+ $separator = str_contains($url, '?') ? '&' : '?';
+ header("Location: " . $url . $separator . "openid_configuration=" . urlencode(ilObjLTIConsumer::getOpenidConfigUrl()) . "®istration_token=" . $regToken);
} catch (Exception $exception) {
ilObjLTIConsumer::sendResponseError(500, "error in ltiregstart.php: " . $exception->getMessage());
}
diff --git a/components/ILIAS/LTIConsumer/resources/ltitoken.php b/components/ILIAS/LTIConsumer/resources/ltitoken.php
index aaccf034fa1a..aae671d70136 100644
--- a/components/ILIAS/LTIConsumer/resources/ltitoken.php
+++ b/components/ILIAS/LTIConsumer/resources/ltitoken.php
@@ -22,6 +22,7 @@
use ILIAS\Filesystem\Exception\IOException;
use Firebase\JWT\JWT;
use Firebase\JWT\JWK;
+use Firebase\JWT\Key;
require_once '../vendor/composer/vendor/autoload.php';
require_once __DIR__ . '/../artifacts/bootstrap_default.php';
@@ -72,7 +73,7 @@
invalidRequest("bad request: no claims");
}
-$clientId = $claims['sub'];
+$clientId = $claims['sub'] ?? '';
if (empty($clientId)) {
invalidRequest("bad request: no claims");
}
@@ -83,13 +84,17 @@
try {
$providerId = ilLTIConsumeProvider::getProviderIdFromClientId($clientId);
} catch (IOException $e) {
- invalidRequest(var_export($e, true));
+ invalidClient(var_export($e, true));
+}
+
+if ($providerId <= 0) {
+ invalidClient("unknown client_id: " . $clientId);
}
try {
$provider = new ilLTIConsumeProvider($providerId);
} catch (IOException $e) {
- serverError(var_export($e, true));
+ invalidClient(var_export($e, true));
}
validateServiceToken($clientAssertion, $provider);
@@ -111,16 +116,34 @@ function validateServiceToken(string $token, ilLTIConsumeProvider $provider): vo
try {
ilObjLTIConsumer::getLogger()->debug("validateServiceToken");
// ToDo: caching
- $jwks = file_get_contents($provider->getPublicKeyset());
- $keyset = json_decode($jwks, true);
- $keys = JWK::parseKeySet($keyset);
+ if ($provider->getKeyType() === 'RSA_KEY') {
+ $publicKey = trim($provider->getPublicKey());
+ if ($publicKey === '') {
+ invalidClient('missing public key');
+ }
+ $keys = new Key($publicKey, 'RS256');
+ } else {
+ $publicKeyset = trim($provider->getPublicKeyset());
+ if ($publicKeyset === '') {
+ invalidClient('missing public keyset');
+ }
+ $jwks = @file_get_contents($publicKeyset);
+ if ($jwks === false) {
+ invalidClient('cannot fetch public keyset');
+ }
+ $keyset = json_decode($jwks, true);
+ if (!is_array($keyset)) {
+ invalidClient('invalid public keyset');
+ }
+ $keys = JWK::parseKeySet($keyset);
+ }
$data = JWT::decode($token, $keys);
//ilObjLTIConsumer::getLogger()->debug(var_export($data, TRUE));
if ($provider->getClientId() != $data->iss || $provider->getClientId() != $data->sub) {
- invalidRequest("invalid clientId");
+ invalidClient("invalid clientId");
}
} catch (Exception $e) {
- serverError(var_export($e, true));
+ invalidClient(var_export($e, true));
}
}
@@ -155,6 +178,7 @@ function serverError(string $log = ""): void
ilObjLTIConsumer::getLogger()->error($log);
}
ilObjLTIConsumer::sendResponseError(500, json_encode(array('error' => "ERROR_OPEN_SSL_CONF")));
+ exit;
}
function invalidRequest(string $log = ""): void
@@ -163,4 +187,14 @@ function invalidRequest(string $log = ""): void
ilObjLTIConsumer::getLogger()->error($log);
}
ilObjLTIConsumer::sendResponseError(400, json_encode(array('error' => 'invalid_request')));
+ exit;
+}
+
+function invalidClient(string $log = ""): void
+{
+ if (!empty($log)) {
+ ilObjLTIConsumer::getLogger()->error($log);
+ }
+ ilObjLTIConsumer::sendResponseError(401, json_encode(array('error' => 'invalid_client')));
+ exit;
}
diff --git a/components/ILIAS/LTIConsumer/templates/default/tpl.lti_content_selection_finished.html b/components/ILIAS/LTIConsumer/templates/default/tpl.lti_content_selection_finished.html
index 2f057e9bc1d6..48294acd8682 100755
--- a/components/ILIAS/LTIConsumer/templates/default/tpl.lti_content_selection_finished.html
+++ b/components/ILIAS/LTIConsumer/templates/default/tpl.lti_content_selection_finished.html
@@ -1,3 +1,17 @@
diff --git a/components/ILIAS/LTIConsumer/templates/default/tpl.lti_initial_login.html b/components/ILIAS/LTIConsumer/templates/default/tpl.lti_initial_login.html
index c97e44974abe..067624f066ec 100755
--- a/components/ILIAS/LTIConsumer/templates/default/tpl.lti_initial_login.html
+++ b/components/ILIAS/LTIConsumer/templates/default/tpl.lti_initial_login.html
@@ -5,7 +5,8 @@
+
\ No newline at end of file
+
diff --git a/components/ILIAS/LTIProvider/classes/class.ilLTIAppEventListener.php b/components/ILIAS/LTIProvider/classes/class.ilLTIAppEventListener.php
index b3d82fb17565..35674705bec4 100644
--- a/components/ILIAS/LTIProvider/classes/class.ilLTIAppEventListener.php
+++ b/components/ILIAS/LTIProvider/classes/class.ilLTIAppEventListener.php
@@ -157,31 +157,18 @@ protected function isLTIAuthMode(string $auth_mode): bool
protected function tryOutcomeService(int $resource, string $ext_account, int $a_status, int $a_percentage): void
{
$resource_link = ResourceLink::fromRecordId($resource, $this->connector);
- if (!$resource_link->hasOutcomesService()) {
+ if (!$resource_link->hasOutcomesService() && !$resource_link->hasScoreService()) {
$this->logger->info('No outcome service available for resource id: ' . $resource);
return;
}
$this->logger->info('Trying outcome service with status ' . $a_status . ' and percentage ' . $a_percentage);
$user = UserResult::fromResourceLink($resource_link, $ext_account);
- if (!$a_percentage && $a_status != ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM) {
- $score = 0;
- } else {
- if ($a_status == ilLPStatus::LP_STATUS_COMPLETED_NUM || $a_status == ilLPStatus::LP_STATUS_FAILED_NUM) {
- $score = $a_percentage / 100;
- } elseif (
- $a_status == ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM
- ) {
- $score = null;
- } else {
- $score = 0;
- }
- }
+ $score = $a_status == ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM ? null : $a_percentage / 100;
$platform = $resource_link->getPlatform();
$platform->accessTokenUrl = $platform->accessTokenUrl
- ?: $platform->getSetting('custom_oauth2_access_token_url')
- ?: \ilObjLTIConsumer::getAccessTokenUrl();
+ ?: $platform->getSetting('custom_oauth2_access_token_url');
$priv = \ilObjLTIConsumer::getPrivateKey();
@@ -191,7 +178,6 @@ protected function tryOutcomeService(int $resource, string $ext_account, int $a_
$tool->jku = \ilObjLTIConsumer::getPublicKeysetUrl();
$tool->requiredScopes = [
"https://purl.imsglobal.org/spec/lti-ags/scope/score",
- "https://purl.imsglobal.org/spec/lti-ags/scope/result.readonly",
];
$tool->signatureMethod = $platform->signatureMethod;
diff --git a/components/ILIAS/LTIProvider/classes/class.ilLTIDataConnector.php b/components/ILIAS/LTIProvider/classes/class.ilLTIDataConnector.php
index 6aaf15c2bd8f..d4ab3b011af5 100644
--- a/components/ILIAS/LTIProvider/classes/class.ilLTIDataConnector.php
+++ b/components/ILIAS/LTIProvider/classes/class.ilLTIDataConnector.php
@@ -72,7 +72,12 @@ public function loadPlatform(Platform | ilLTIPlatform $platform): bool
$types = array('integer');
$values = array($id);
} elseif (!empty($platform->platformId)) {
- if (empty($platform->clientId)) {
+ if (empty($platform->clientId) && !empty($platform->deploymentId)) {
+ $allowMultiple = true;
+ $query .= '(platform_id = %s) AND (deployment_id = %s)';
+ $types = array('text', 'text');
+ $values = array($platform->platformId, $platform->deploymentId);
+ } elseif (empty($platform->clientId)) {
$allowMultiple = true;
$query .= '(platform_id = %s)';
$types = array('text');
diff --git a/components/ILIAS/Tracking/classes/status/class.ilLPStatusLtiOutcome.php b/components/ILIAS/Tracking/classes/status/class.ilLPStatusLtiOutcome.php
index b8a5eb52bc85..9422194eb7d1 100755
--- a/components/ILIAS/Tracking/classes/status/class.ilLPStatusLtiOutcome.php
+++ b/components/ILIAS/Tracking/classes/status/class.ilLPStatusLtiOutcome.php
@@ -133,11 +133,45 @@ private function ensureObject(int $objId, $object): ilObjLTIConsumer
return $object;
}
+ private function getLatestAgsGrade(int $objId, int $usrId): ?array
+ {
+ global $DIC;
+
+ $db = $DIC->database();
+ if (!$db->tableExists('lti_consumer_grades')) {
+ return null;
+ }
+
+ $query = 'SELECT * FROM lti_consumer_grades'
+ . ' WHERE obj_id = ' . $db->quote($objId, 'integer')
+ . ' AND usr_id = ' . $db->quote($usrId, 'integer')
+ . ' ORDER BY lti_timestamp DESC, stored DESC, id DESC';
+ $res = $db->query($query);
+ $row = $db->fetchAssoc($res);
+
+ return $row ?: null;
+ }
+
public function determineStatus(
int $a_obj_id,
int $a_usr_id,
?object $a_obj = null
): int {
+ global $DIC;
+ $logger = $DIC->logger()->root();
+
+ $latestGrade = $this->getLatestAgsGrade($a_obj_id, $a_usr_id);
+ if ($latestGrade !== null) {
+ $activityProgress = ilLTIConsumerActivityProgress::tryFrom((string) ($latestGrade['activity_progress'] ?? ''));
+ $gradingProgress = ilLTIConsumerGradingProgress::tryFrom((string) ($latestGrade['grading_progress'] ?? ''));
+
+ if (($activityProgress?->isInProgress() ?? false) ||
+ ($activityProgress === ilLTIConsumerActivityProgress::SUBMITTED && $gradingProgress?->isPending()) ||
+ ($gradingProgress?->isPending() ?? false)) {
+ return self::LP_STATUS_IN_PROGRESS_NUM;
+ }
+ }
+
$ltiResult = $this->getLtiUserResult($a_obj_id, $a_usr_id);
if ($ltiResult instanceof ilLTIConsumerResult) {
@@ -159,6 +193,14 @@ public function determinePercentage(
int $a_usr_id,
?object $a_obj = null
): int {
+ $latestGrade = $this->getLatestAgsGrade($a_obj_id, $a_usr_id);
+ if ($latestGrade !== null &&
+ is_numeric($latestGrade['score_given'] ?? null) &&
+ is_numeric($latestGrade['score_maximum'] ?? null) &&
+ (float) $latestGrade['score_maximum'] > 0) {
+ return (int) round(((float) $latestGrade['score_given'] / (float) $latestGrade['score_maximum']) * 100);
+ }
+
$ltiResult = $this->getLtiUserResult($a_obj_id, $a_usr_id);
if ($ltiResult instanceof ilLTIConsumerResult) {
diff --git a/lang/ilias_ar.lang b/lang/ilias_ar.lang
index 1e030b208ba7..acac79e558cc 100644
--- a/lang/ilias_ar.lang
+++ b/lang/ilias_ar.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#Activity ID###07 02 2020 new variable
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.###07 02 2020 new variable
lti#:#auth_lti#:#LTI Auth###31 08 2017 new variable
lti#:#conf_privacy_ident#:#User identification###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###26 08 2024 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
@@ -11378,7 +11376,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Authentication failed, no valid consumer key given.###31 08 2017 new variable
lti#:#lti_con_content_item#:#Support for Deep Linking###26 08 2024 new variable
lti#:#lti_con_content_item_url#:#Content URL###26 08 2024 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###26 08 2024 new variable
lti#:#lti_con_key_type#:#Public Key Type###26 08 2024 new variable
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users###
lti#:#lti_cron_title#:#LTI Outcome Service###07 02 2020 new variable
lti#:#lti_cron_title_desc#:#Synchronizes the learning progress of LTI users with the LTI consumer, if it supports the outcome service. This cron job is only required to transfer status updates after Learning progress settings updates.###07 02 2020 new variable
lti#:#lti_custom_new#:#Create Own Provider Settings###07 02 2020 new variable
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Consumers created in Administration do not allow content selection
lti#:#lti_delete_consume_provider#:#Delete Provider###07 02 2020 new variable
lti#:#lti_delete_consume_providers#:#Delete Providers###07 02 2020 new variable
lti#:#lti_delete_provider#:#Delete Provider###07 02 2020 new variable
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#Edit LTI Consumer###31 08 2017 new variable
lti#:#lti_exit#:#Close LTI Session###31 08 2017 new variable
lti#:#lti_exited#:#LTI Session closed###31 08 2017 new variable
lti#:#lti_exited_info#:#LTI Session successfully closed###31 08 2017 new variable
+lti#:#lti_form_provider_content_selection#:#اختيار المحتوى
lti#:#lti_form_provider_create#:#Create Provider Settings###07 02 2020 new variable
lti#:#lti_form_provider_edit#:#Edit Provider Settings###07 02 2020 new variable
lti#:#lti_form_section_appearance#:#Options for launch###07 02 2020 new variable
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#Certificate###07 02 2020 new variable
lti#:#subtab_object_settings#:#Object Settings###07 02 2020 new variable
lti#:#subtab_provider_settings#:#LTI Provider Settings###07 02 2020 new variable
lti#:#tab_content#:#Content###07 02 2020 new variable
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info###07 02 2020 new variable
lti#:#tab_scoring#:#Ranking###07 02 2020 new variable
lti#:#tab_settings#:#Settings###07 02 2020 new variable
diff --git a/lang/ilias_bg.lang b/lang/ilias_bg.lang
index 4a03d88d4c72..9f84035fd5fc 100644
--- a/lang/ilias_bg.lang
+++ b/lang/ilias_bg.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#Activity ID###07 02 2020 new variable
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.###07 02 2020 new variable
lti#:#auth_lti#:#LTI Auth###31 08 2017 new variable
lti#:#conf_privacy_ident#:#User identification###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###26 08 2024 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###21 05 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###21 05 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###21 05 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
@@ -11378,7 +11376,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Authentication failed, no valid consumer key given.###31 08 2017 new variable
lti#:#lti_con_content_item#:#Support for Deep Linking###26 08 2024 new variable
lti#:#lti_con_content_item_url#:#Content URL###26 08 2024 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###26 08 2024 new variable
lti#:#lti_con_key_type#:#Public Key Type###26 08 2024 new variable
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users###
lti#:#lti_cron_title#:#LTI Outcome Service###07 02 2020 new variable
lti#:#lti_cron_title_desc#:#Synchronizes the learning progress of LTI users with the LTI consumer, if it supports the outcome service. This cron job is only required to transfer status updates after Learning progress settings updates.###07 02 2020 new variable
lti#:#lti_custom_new#:#Create Own Provider Settings###07 02 2020 new variable
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Consumers created in Administration do not allow content selection
lti#:#lti_delete_consume_provider#:#Delete Provider###07 02 2020 new variable
lti#:#lti_delete_consume_providers#:#Delete Providers###07 02 2020 new variable
lti#:#lti_delete_provider#:#Delete Provider###07 02 2020 new variable
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#Edit LTI Consumer###31 08 2017 new variable
lti#:#lti_exit#:#Close LTI Session###31 08 2017 new variable
lti#:#lti_exited#:#LTI Session closed###31 08 2017 new variable
lti#:#lti_exited_info#:#LTI Session successfully closed###31 08 2017 new variable
+lti#:#lti_form_provider_content_selection#:#Избор на съдържание
lti#:#lti_form_provider_create#:#Create Provider Settings###07 02 2020 new variable
lti#:#lti_form_provider_edit#:#Edit Provider Settings###07 02 2020 new variable
lti#:#lti_form_section_appearance#:#Options for launch###07 02 2020 new variable
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#Certificate###07 02 2020 new variable
lti#:#subtab_object_settings#:#Object Settings###07 02 2020 new variable
lti#:#subtab_provider_settings#:#LTI Provider Settings###07 02 2020 new variable
lti#:#tab_content#:#Content###07 02 2020 new variable
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info###07 02 2020 new variable
lti#:#tab_scoring#:#Ranking###07 02 2020 new variable
lti#:#tab_settings#:#Settings###07 02 2020 new variable
diff --git a/lang/ilias_cs.lang b/lang/ilias_cs.lang
index a2ed6720507a..765ffc5a1f5f 100644
--- a/lang/ilias_cs.lang
+++ b/lang/ilias_cs.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#Activity ID###07 02 2020 new variable
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.###07 02 2020 new variable
lti#:#auth_lti#:#LTI Auth
lti#:#conf_privacy_ident#:#User identification###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###26 08 2024 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
@@ -11378,7 +11376,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Ověřování se nezdařilo, nebyl zadán žádný platný spotřebitelský klíč.
lti#:#lti_con_content_item#:#Support for Deep Linking###26 08 2024 new variable
lti#:#lti_con_content_item_url#:#Content URL###26 08 2024 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###26 08 2024 new variable
lti#:#lti_con_key_type#:#Public Key Type###26 08 2024 new variable
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users###
lti#:#lti_cron_title#:#Služba LTI Outcome Service
lti#:#lti_cron_title_desc#:#Synchronizuje průběh učení uživatelů LTI se spotřebitelem LTI, pokud podporuje službu výstupu. Tato úloha cron je vyžadována pouze pro přenos aktualizací statusu po aktualizacích nastavení postupu výuky.
lti#:#lti_custom_new#:#Create Own Provider Settings###07 02 2020 new variable
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Spotřebitelé vytvoření ve správě neumožňují výběr obsahu
lti#:#lti_delete_consume_provider#:#Delete Provider###07 02 2020 new variable
lti#:#lti_delete_consume_providers#:#Delete Providers###07 02 2020 new variable
lti#:#lti_delete_provider#:#Delete Provider###07 02 2020 new variable
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#Upravit spotřebitele LTI
lti#:#lti_exit#:#Ukončit relaci LTI
lti#:#lti_exited#:#Relace LTI byla ukončena
lti#:#lti_exited_info#:#Relace LTI byla úspěšně ukončena
+lti#:#lti_form_provider_content_selection#:#Výběr obsahu
lti#:#lti_form_provider_create#:#Create Provider Settings###07 02 2020 new variable
lti#:#lti_form_provider_edit#:#Edit Provider Settings###07 02 2020 new variable
lti#:#lti_form_section_appearance#:#Options for launch###07 02 2020 new variable
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#Certificate###07 02 2020 new variable
lti#:#subtab_object_settings#:#Object Settings###07 02 2020 new variable
lti#:#subtab_provider_settings#:#LTI Provider Settings###07 02 2020 new variable
lti#:#tab_content#:#Content###07 02 2020 new variable
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info###07 02 2020 new variable
lti#:#tab_scoring#:#Ranking###07 02 2020 new variable
lti#:#tab_settings#:#Settings###07 02 2020 new variable
diff --git a/lang/ilias_da.lang b/lang/ilias_da.lang
index 6e108f56088c..22752d3955fa 100644
--- a/lang/ilias_da.lang
+++ b/lang/ilias_da.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#Activity ID###07 02 2020 new variable
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.###07 02 2020 new variable
lti#:#auth_lti#:#LTI Auth###31 08 2017 new variable
lti#:#conf_privacy_ident#:#User identification###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###26 08 2024 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
@@ -11378,7 +11376,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Authentication failed, no valid consumer key given.###31 08 2017 new variable
lti#:#lti_con_content_item#:#Support for Deep Linking###26 08 2024 new variable
lti#:#lti_con_content_item_url#:#Content URL###26 08 2024 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###26 08 2024 new variable
lti#:#lti_con_key_type#:#Public Key Type###26 08 2024 new variable
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users###
lti#:#lti_cron_title#:#LTI Outcome Service###07 02 2020 new variable
lti#:#lti_cron_title_desc#:#Synchronizes the learning progress of LTI users with the LTI consumer, if it supports the outcome service. This cron job is only required to transfer status updates after Learning progress settings updates.###07 02 2020 new variable
lti#:#lti_custom_new#:#Create Own Provider Settings###07 02 2020 new variable
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Consumers created in Administration do not allow content selection
lti#:#lti_delete_consume_provider#:#Delete Provider###07 02 2020 new variable
lti#:#lti_delete_consume_providers#:#Delete Providers###07 02 2020 new variable
lti#:#lti_delete_provider#:#Delete Provider###07 02 2020 new variable
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#Edit LTI Consumer###31 08 2017 new variable
lti#:#lti_exit#:#Close LTI Session###31 08 2017 new variable
lti#:#lti_exited#:#LTI Session closed###31 08 2017 new variable
lti#:#lti_exited_info#:#LTI Session successfully closed###31 08 2017 new variable
+lti#:#lti_form_provider_content_selection#:#Valg af indhold
lti#:#lti_form_provider_create#:#Create Provider Settings###07 02 2020 new variable
lti#:#lti_form_provider_edit#:#Edit Provider Settings###07 02 2020 new variable
lti#:#lti_form_section_appearance#:#Options for launch###07 02 2020 new variable
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#Certificate###07 02 2020 new variable
lti#:#subtab_object_settings#:#Object Settings###07 02 2020 new variable
lti#:#subtab_provider_settings#:#LTI Provider Settings###07 02 2020 new variable
lti#:#tab_content#:#Content###07 02 2020 new variable
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info###07 02 2020 new variable
lti#:#tab_scoring#:#Ranking###07 02 2020 new variable
lti#:#tab_settings#:#Settings###07 02 2020 new variable
diff --git a/lang/ilias_de.lang b/lang/ilias_de.lang
index 7ad75bad26ec..98639bca54a2 100644
--- a/lang/ilias_de.lang
+++ b/lang/ilias_de.lang
@@ -11260,16 +11260,14 @@ lti#:#activity_id#:#Activity-ID
lti#:#activity_id_info#:#Diese Activity-ID wird vom LTI-Provider verwendet, um Statements zu identifizieren.
lti#:#auth_lti#:#LTI Auth
lti#:#conf_privacy_ident#:#Identifikation der Person
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash kombiniert mit einer eindeutigen ILIAS-Plattform-ID, die als E-Mail-Adresse formatiert ist
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#Die Identifikation ist identisch bei jedem Aufruf, aber lässt keine direkten Rückschlüsse auf das ILIAS-Konto und die zugehörige Person zu.
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash@ILIAS-Plattform-ID.ilias###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#Die E-Mail-Adresse setzt sich zusammen aus einem Hash-Wert und einer eigens generierten Plattform-ID. Ohne Zugriff auf die ILIAS-Datenbank ermöglicht diese Option keine direkten Rückschlüsse auf ein ILIAS-Konto.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#Die externe Konten-ID wird kombiniert mit einer eindeutigen ID der ILIAS-Plattform und als E-Mail-Adresse formatiert.
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#Die Identifikation ist identisch bei jedem Aufruf und lässt direkte Rückschlüsse auf das ILIAS-Konto und die zugehörige Person zu.
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS-Anmeldename kombiniert mit einer eindeutigen ILIAS-Plattform-ID, die als E-Mail-Adresse formatiert ist.
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sendet den Anmeldenamen. Dies ist identisch mit jedem Aufruf, kann aber direkte Rückschlüsse auf den ILIAS-Benutzer zulassen.
lti#:#conf_privacy_ident_il_uuid_random#:#Zufalls-ID@ILIAS-Plattform-ID.ilias###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#Pro ILIAS-Objekt und ILIAS-Konto wird eine Zufalls-ID erzeugt, die bei jedem Aufruf identisch bleibt. Die E-Mail-Adresse setzt sich zusammen aus der Zufalls-ID und einer eigens###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash@ILIAS-Plattform-ID.ilias###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#Die E-Mail-Adresse setzt sich zusammen aus einem Hash-Wert und einer eigens generierten Plattform-ID. Ohne Zugriff auf die ILIAS-Datenbank ermöglicht diese Option keine direkten Rückschlüsse auf ein ILIAS-Konto.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash@ILIAS-Domain###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#Die E-Mail-Adresse setzt sich zusammen aus einem Hash-Wert und einer ILIAS-Domain. Diese Option ist mit maximal 80 Zeichen deutlich kürzer als die mit ILIAS-Plattform-ID. Ohne Zugriff auf die ILIAS-Datenbank ermöglicht diese Option sind nur sehr eingeschränkte Rückschlüsse auf ein ILIAS-Konto.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ID des ILIAS-Kontos kombiniert mit einer eindeutigen ILIAS-Plattform-ID, die als E-Mail-Adresse formatiert ist
@@ -11380,7 +11378,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#Mindestens ein Provider konnte nicht ge
lti#:#lti_auth_failed_invalid_key#:#Authentifizierung nicht möglich. Es wurde kein gültiger Consumer-Key übermittelt.
lti#:#lti_con_content_item#:#Unterstützung für Deep Linking
lti#:#lti_con_content_item_url#:#Inhalts-URL
-lti#:#lti_con_grade_synchronization#:#Erweiterte Benotungsdienste###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#Das LTI-Tool muss 'Assignment and Grade Services' anbieten.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL
lti#:#lti_con_key_type#:#Typ des öffentlichen Schlüssels
@@ -11470,6 +11468,7 @@ lti#:#lti_create_lti_user_role#:#Empfohlene globale Rolle für LTI-User anlegen
lti#:#lti_cron_title#:#LTI Outcome Service
lti#:#lti_cron_title_desc#:#Überträgt den Lernfortschritt von LTI-Benutzern an die aufrufende Plattform. Dieser Cron-Job wird nur in den Fällen benötigt, wenn der Lernfortschritt aufgrund von Einstellungsänderungen neu berechnet werden muss.
lti#:#lti_custom_new#:#Eigene Provider-Einstellungen anlegen
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#In der Administration angelegte Konsumenten erlauben keine Inhaltsauswahl
lti#:#lti_delete_consume_provider#:#Provider löschen
lti#:#lti_delete_consume_providers#:#Provider löschen
lti#:#lti_delete_provider#:#Provider löschen
@@ -11478,6 +11477,7 @@ lti#:#lti_edit_consumer#:#LTI-Konsument bearbeiten
lti#:#lti_exit#:#LTI-Sitzung beenden
lti#:#lti_exited#:#LTI-Sitzung beendet
lti#:#lti_exited_info#:#Die LTI-Sitzung wurde erfolgreich beendet.
+lti#:#lti_form_provider_content_selection#:#Inhaltsauswahl
lti#:#lti_form_provider_create#:#Provider-Einstellungen anlegen
lti#:#lti_form_provider_edit#:#Provider-Einstellungen bearbeiten
lti#:#lti_form_section_appearance#:#Optionen für den Start
@@ -11529,6 +11529,7 @@ lti#:#subtab_certificate#:#Zertifikat
lti#:#subtab_object_settings#:#Objekteinstellungen
lti#:#subtab_provider_settings#:#LTI-Provider-Einstellungen
lti#:#tab_content#:#Inhalt
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info
lti#:#tab_scoring#:#Platzierungen
lti#:#tab_settings#:#Einstellungen
diff --git a/lang/ilias_el.lang b/lang/ilias_el.lang
index ce53670350c6..d03afd460b74 100644
--- a/lang/ilias_el.lang
+++ b/lang/ilias_el.lang
@@ -11259,16 +11259,14 @@ lti#:#activity_id#:#Activity ID###07 02 2020 new variable
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.###07 02 2020 new variable
lti#:#auth_lti#:#LTI Auth###31 08 2017 new variable
lti#:#conf_privacy_ident#:#User identification###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###26 08 2024 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
@@ -11379,7 +11377,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Authentication failed, no valid consumer key given.###31 08 2017 new variable
lti#:#lti_con_content_item#:#Support for Deep Linking###26 08 2024 new variable
lti#:#lti_con_content_item_url#:#Content URL###26 08 2024 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###26 08 2024 new variable
lti#:#lti_con_key_type#:#Public Key Type###26 08 2024 new variable
@@ -11469,6 +11467,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users###
lti#:#lti_cron_title#:#LTI Outcome Service###07 02 2020 new variable
lti#:#lti_cron_title_desc#:#Synchronizes the learning progress of LTI users with the LTI consumer, if it supports the outcome service. This cron job is only required to transfer status updates after Learning progress settings updates.###07 02 2020 new variable
lti#:#lti_custom_new#:#Create Own Provider Settings###07 02 2020 new variable
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Consumers created in Administration do not allow content selection
lti#:#lti_delete_consume_provider#:#Delete Provider###07 02 2020 new variable
lti#:#lti_delete_consume_providers#:#Delete Providers###07 02 2020 new variable
lti#:#lti_delete_provider#:#Delete Provider###07 02 2020 new variable
@@ -11477,6 +11476,7 @@ lti#:#lti_edit_consumer#:#Edit LTI Consumer###31 08 2017 new variable
lti#:#lti_exit#:#Close LTI Session###31 08 2017 new variable
lti#:#lti_exited#:#LTI Session closed###31 08 2017 new variable
lti#:#lti_exited_info#:#LTI Session successfully closed###31 08 2017 new variable
+lti#:#lti_form_provider_content_selection#:#Επιλογή περιεχομένου
lti#:#lti_form_provider_create#:#Create Provider Settings###07 02 2020 new variable
lti#:#lti_form_provider_edit#:#Edit Provider Settings###07 02 2020 new variable
lti#:#lti_form_section_appearance#:#Options for launch###07 02 2020 new variable
@@ -11528,6 +11528,7 @@ lti#:#subtab_certificate#:#Certificate###07 02 2020 new variable
lti#:#subtab_object_settings#:#Object Settings###07 02 2020 new variable
lti#:#subtab_provider_settings#:#LTI Provider Settings###07 02 2020 new variable
lti#:#tab_content#:#Content###07 02 2020 new variable
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info###07 02 2020 new variable
lti#:#tab_scoring#:#Ranking###07 02 2020 new variable
lti#:#tab_settings#:#Settings###07 02 2020 new variable
diff --git a/lang/ilias_en.lang b/lang/ilias_en.lang
index 01613ba21707..b511affcc1de 100644
--- a/lang/ilias_en.lang
+++ b/lang/ilias_en.lang
@@ -11261,16 +11261,14 @@ lti#:#activity_id#:#Activity ID
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.
lti#:#auth_lti#:#LTI Auth
lti#:#conf_privacy_ident#:#User identification
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address
@@ -11381,7 +11379,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Authentication failed, no valid consumer key given.
lti#:#lti_con_content_item#:#Support for Deep Linking
lti#:#lti_con_content_item_url#:#Content URL
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL
lti#:#lti_con_key_type#:#Public Key Type
@@ -11471,6 +11469,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users
lti#:#lti_cron_title#:#LTI Outcome Service
lti#:#lti_cron_title_desc#:#Synchronizes the learning progress of LTI users with the LTI consumer, if it supports the outcome service. This cron job is only required to transfer status updates after Learning progress settings updates.
lti#:#lti_custom_new#:#Create Own Provider Settings
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Consumers created in Administration do not allow content selection
lti#:#lti_delete_consume_provider#:#Delete Provider
lti#:#lti_delete_consume_providers#:#Delete Providers
lti#:#lti_delete_provider#:#Delete Provider
@@ -11479,6 +11478,7 @@ lti#:#lti_edit_consumer#:#Edit LTI Consumer
lti#:#lti_exit#:#Close LTI Session
lti#:#lti_exited#:#LTI Session closed
lti#:#lti_exited_info#:#LTI Session successfully closed
+lti#:#lti_form_provider_content_selection#:#Content Selection
lti#:#lti_form_provider_create#:#Create Provider Settings
lti#:#lti_form_provider_edit#:#Edit Provider Settings
lti#:#lti_form_section_appearance#:#Options for launch
@@ -11530,6 +11530,7 @@ lti#:#subtab_certificate#:#Certificate
lti#:#subtab_object_settings#:#Object Settings
lti#:#subtab_provider_settings#:#LTI Provider Settings
lti#:#tab_content#:#Content
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info
lti#:#tab_scoring#:#Ranking
lti#:#tab_settings#:#Settings
diff --git a/lang/ilias_es.lang b/lang/ilias_es.lang
index 527bf30102eb..682d67fc569f 100644
--- a/lang/ilias_es.lang
+++ b/lang/ilias_es.lang
@@ -11268,16 +11268,14 @@ lti#:#activity_id#:#ID de actividad
lti#:#activity_id_info#:#Este ID de actividad es utilizado por el proveedor LTI para identificar declaraciones.
lti#:#auth_lti#:#Autenticación LTI
lti#:#conf_privacy_ident#:#Identificación de usuario
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combinado con un ID de plataforma ILIAS único con formato de dirección de correo electrónico
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#Esto es idéntico para cada llamada, pero no permite ninguna conclusión directa sobre el usuario de ILIAS.
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combinado con un ID de plataforma ILIAS único con formato de dirección de correo electrónico
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#Esto es idéntico para cada llamada, pero no permite ninguna conclusión directa sobre el usuario de ILIAS.
lti#:#conf_privacy_ident_il_uuid_ext_account#:#ID de usuario externo combinado con un ID de plataforma ILIAS único con formato de dirección de correo electrónico
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#Esto es idéntico para cada llamada, pero puede permitir una conclusión directa sobre el usuario.
lti#:#conf_privacy_ident_il_uuid_login#:#Nombre de usuario de ILIAS combinado con un ID de plataforma ILIAS único con formato de dirección de correo electrónico
lti#:#conf_privacy_ident_il_uuid_login_info#:#Envía el nombre de usuario. Esto es idéntico para cada llamada, pero puede permitir una conclusión directa sobre el usuario de ILIAS.
lti#:#conf_privacy_ident_il_uuid_random#:#ID aleatorio combinado con un ID de plataforma ILIAS único con formato de dirección de correo electrónico
lti#:#conf_privacy_ident_il_uuid_random_info#:#Para cada objeto ILIAS y usuario de ILIAS se genera un ID aleatorio que permanece idéntico para cada llamada. Las conclusiones sobre un usuario son muy limitadas porque es prácticamente imposible crear perfiles de usuario a través de los objetos.
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combinado con un ID de plataforma ILIAS único con formato de dirección de correo electrónico
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#Esto es idéntico para cada llamada, pero no permite ninguna conclusión directa sobre el usuario de ILIAS.
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combinado con el dominio de ILIAS con formato de dirección de correo electrónico.
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#Esto es idéntico para cada llamada, con un máximo de 80 caracteres, significativamente más corto que la variante con el ID de la plataforma ILIAS y permite solo conclusiones muy limitadas sobre el usuario de ILIAS.
lti#:#conf_privacy_ident_il_uuid_user_id#:#ID de usuario de ILIAS combinado con un ID de plataforma ILIAS único con formato de dirección de correo electrónico
@@ -11388,8 +11386,8 @@ lti#:#lti_at_least_one_prov_has_usages#:#Al menos un proveedor no pudo ser elimi
lti#:#lti_auth_failed_invalid_key#:#Error de autenticación, no se proporcionó una clave de consumidor válida.
lti#:#lti_con_content_item#:#Soporte para Deep Linking
lti#:#lti_con_content_item_url#:#URL de Contenido
-lti#:#lti_con_grade_synchronization#:#Servicios Avanzados de Calificación
-lti#:#lti_con_grade_synchronization_info#:#La herramienta LTI debe ofrecer 'Servicios de Tareas y Calificaciones' (Assignment and Grade Services).
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services
+lti#:#lti_con_grade_synchronization_info#:#La herramienta LTI debe ofrecer 'Assignment and Grade Services'.
lti#:#lti_con_initiate_login_url#:#URL de Inicio de Sesión
lti#:#lti_con_key_type#:#Tipo de Clave Pública
lti#:#lti_con_key_type_jwk#:#URL (Json Web Token)
@@ -11478,6 +11476,7 @@ lti#:#lti_create_lti_user_role#:#Crear el rol global recomendado para usuarios L
lti#:#lti_cron_title#:#Servicio de Resultados LTI (Outcome Service)
lti#:#lti_cron_title_desc#:#Sincroniza el progreso de aprendizaje de los usuarios de LTI con el consumidor de LTI, si este es compatible con el servicio de resultados. Esta tarea programada (cron job) sólo es necesaria para transferir actualizaciones de estado tras la actualización de la configuración del progreso de aprendizaje.
lti#:#lti_custom_new#:#Crear ajustes de proveedor propios
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Los Consumidores creados desde Administración no permiten la selección de contenido
lti#:#lti_delete_consume_provider#:#Eliminar Proveedor
lti#:#lti_delete_consume_providers#:#Eliminar Proveedores
lti#:#lti_delete_provider#:#Eliminar Proveedor
@@ -11486,6 +11485,7 @@ lti#:#lti_edit_consumer#:#Editar Consumidor LTI
lti#:#lti_exit#:#Cerrar sesión LTI
lti#:#lti_exited#:#Sesión LTI cerrada
lti#:#lti_exited_info#:#Sesión LTI cerrada con éxito
+lti#:#lti_form_provider_content_selection#:#Selección de contenido
lti#:#lti_form_provider_create#:#Crear configuración de proveedor
lti#:#lti_form_provider_edit#:#Editar configuración de proveedor
lti#:#lti_form_section_appearance#:#Opciones de lanzamiento
@@ -11537,6 +11537,7 @@ lti#:#subtab_certificate#:#Certificado
lti#:#subtab_object_settings#:#Configuración del objeto
lti#:#subtab_provider_settings#:#Configuración del proveedor LTI
lti#:#tab_content#:#Contenido
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Información
lti#:#tab_scoring#:#Ranking
lti#:#tab_settings#:#Configuración
diff --git a/lang/ilias_et.lang b/lang/ilias_et.lang
index 102891ea0c96..ff427bb16078 100644
--- a/lang/ilias_et.lang
+++ b/lang/ilias_et.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#Activity ID###07 02 2020 new variable
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.###07 02 2020 new variable
lti#:#auth_lti#:#LTI Auth###31 08 2017 new variable
lti#:#conf_privacy_ident#:#User identification###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###26 08 2024 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
@@ -11378,7 +11376,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Authentication failed, no valid consumer key given.###31 08 2017 new variable
lti#:#lti_con_content_item#:#Support for Deep Linking###26 08 2024 new variable
lti#:#lti_con_content_item_url#:#Content URL###26 08 2024 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###26 08 2024 new variable
lti#:#lti_con_key_type#:#Public Key Type###26 08 2024 new variable
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users###
lti#:#lti_cron_title#:#LTI Outcome Service###07 02 2020 new variable
lti#:#lti_cron_title_desc#:#Synchronizes the learning progress of LTI users with the LTI consumer, if it supports the outcome service. This cron job is only required to transfer status updates after Learning progress settings updates.###07 02 2020 new variable
lti#:#lti_custom_new#:#Create Own Provider Settings###07 02 2020 new variable
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Consumers created in Administration do not allow content selection
lti#:#lti_delete_consume_provider#:#Delete Provider###07 02 2020 new variable
lti#:#lti_delete_consume_providers#:#Delete Providers###07 02 2020 new variable
lti#:#lti_delete_provider#:#Delete Provider###07 02 2020 new variable
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#Edit LTI Consumer###31 08 2017 new variable
lti#:#lti_exit#:#Close LTI Session###31 08 2017 new variable
lti#:#lti_exited#:#LTI Session closed###31 08 2017 new variable
lti#:#lti_exited_info#:#LTI Session successfully closed###31 08 2017 new variable
+lti#:#lti_form_provider_content_selection#:#Sisu valik
lti#:#lti_form_provider_create#:#Create Provider Settings###07 02 2020 new variable
lti#:#lti_form_provider_edit#:#Edit Provider Settings###07 02 2020 new variable
lti#:#lti_form_section_appearance#:#Options for launch###07 02 2020 new variable
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#Certificate###07 02 2020 new variable
lti#:#subtab_object_settings#:#Object Settings###07 02 2020 new variable
lti#:#subtab_provider_settings#:#LTI Provider Settings###07 02 2020 new variable
lti#:#tab_content#:#Content###07 02 2020 new variable
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info###07 02 2020 new variable
lti#:#tab_scoring#:#Ranking###07 02 2020 new variable
lti#:#tab_settings#:#Settings###07 02 2020 new variable
diff --git a/lang/ilias_fa.lang b/lang/ilias_fa.lang
index 11f11b12d168..281478d65355 100644
--- a/lang/ilias_fa.lang
+++ b/lang/ilias_fa.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#Activity ID###07 02 2020 new variable
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.###07 02 2020 new variable
lti#:#auth_lti#:#LTI Auth###31 08 2017 new variable
lti#:#conf_privacy_ident#:#User identification###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###26 08 2024 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
@@ -11378,7 +11376,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Authentication failed, no valid consumer key given.###31 08 2017 new variable
lti#:#lti_con_content_item#:#Support for Deep Linking###26 08 2024 new variable
lti#:#lti_con_content_item_url#:#Content URL###26 08 2024 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###26 08 2024 new variable
lti#:#lti_con_key_type#:#Public Key Type###26 08 2024 new variable
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users###
lti#:#lti_cron_title#:#LTI Outcome Service###07 02 2020 new variable
lti#:#lti_cron_title_desc#:#Synchronizes the learning progress of LTI users with the LTI consumer, if it supports the outcome service. This cron job is only required to transfer status updates after Learning progress settings updates.###07 02 2020 new variable
lti#:#lti_custom_new#:#Create Own Provider Settings###07 02 2020 new variable
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Consumers created in Administration do not allow content selection
lti#:#lti_delete_consume_provider#:#Delete Provider###07 02 2020 new variable
lti#:#lti_delete_consume_providers#:#Delete Providers###07 02 2020 new variable
lti#:#lti_delete_provider#:#Delete Provider###07 02 2020 new variable
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#Edit LTI Consumer###31 08 2017 new variable
lti#:#lti_exit#:#Close LTI Session###31 08 2017 new variable
lti#:#lti_exited#:#LTI Session closed###31 08 2017 new variable
lti#:#lti_exited_info#:#LTI Session successfully closed###31 08 2017 new variable
+lti#:#lti_form_provider_content_selection#:#انتخاب محتوا
lti#:#lti_form_provider_create#:#Create Provider Settings###07 02 2020 new variable
lti#:#lti_form_provider_edit#:#Edit Provider Settings###07 02 2020 new variable
lti#:#lti_form_section_appearance#:#Options for launch###07 02 2020 new variable
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#Certificate###07 02 2020 new variable
lti#:#subtab_object_settings#:#Object Settings###07 02 2020 new variable
lti#:#subtab_provider_settings#:#LTI Provider Settings###07 02 2020 new variable
lti#:#tab_content#:#Content###07 02 2020 new variable
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info###07 02 2020 new variable
lti#:#tab_scoring#:#Ranking###07 02 2020 new variable
lti#:#tab_settings#:#Settings###07 02 2020 new variable
diff --git a/lang/ilias_fr.lang b/lang/ilias_fr.lang
index 6d73709d6bcc..579d23e1dce9 100644
--- a/lang/ilias_fr.lang
+++ b/lang/ilias_fr.lang
@@ -11243,16 +11243,14 @@ lti#:#activity_id#:#Activity ID
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.
lti#:#auth_lti#:#Auteur LTI
lti#:#conf_privacy_ident#:#User identification
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###31 10 2023 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###31 10 2023 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User Id combined with a unique ILIAS platform id formated as an email adress.
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formated as an email adress.
lti#:#conf_privacy_ident_il_uuid_login_info#:#This is identical to each call, but may allow a direct conclusion about the ILIAS user.
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formated as an email adress.
@@ -11363,8 +11361,8 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Authentification échouée, aucune clé consommateur valide donnée.
lti#:#lti_con_content_item#:#Support for Deep Linking###31 10 2023 new variable
lti#:#lti_con_content_item_url#:#Content URL###31 10 2023 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
-lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization_info#:#L'outil LTI doit proposer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###31 10 2023 new variable
lti#:#lti_con_key_type#:#Public Key Type###31 10 2023 new variable
lti#:#lti_con_key_type_jwk#:#URL (Json Web Token)###31 10 2023 new variable
@@ -11453,6 +11451,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users
lti#:#lti_cron_title#:#LTI Outcome Service
lti#:#lti_cron_title_desc#:#Synchronizes the learning progress of LTI users with the LTI consumer, if it supports the outcome service. This cron job is only required to transfer status updates after Learning progress settings updates.
lti#:#lti_custom_new#:#Create Own Provider Settings
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Les consommateurs créés dans l'administration ne permettent pas la sélection de contenu
lti#:#lti_delete_consume_provider#:#Delete Provider
lti#:#lti_delete_consume_providers#:#Delete Providers
lti#:#lti_delete_provider#:#Delete Provider
@@ -11461,6 +11460,7 @@ lti#:#lti_edit_consumer#:#Éditer consommateur LTI
lti#:#lti_exit#:#Fermer session LTI
lti#:#lti_exited#:#Session LTI fermée
lti#:#lti_exited_info#:#Session LTI fermée avec succès
+lti#:#lti_form_provider_content_selection#:#Sélection de contenu
lti#:#lti_form_provider_create#:#Create Provider Settings
lti#:#lti_form_provider_edit#:#Edit Provider Settings
lti#:#lti_form_section_appearance#:#Options for launch
@@ -11512,6 +11512,7 @@ lti#:#subtab_certificate#:#Certificate
lti#:#subtab_object_settings#:#Object Settings
lti#:#subtab_provider_settings#:#LTI Provider Settings
lti#:#tab_content#:#Content
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info
lti#:#tab_scoring#:#Ranking
lti#:#tab_settings#:#Settings
diff --git a/lang/ilias_hr.lang b/lang/ilias_hr.lang
index 72ab101c56b4..8d186025004c 100644
--- a/lang/ilias_hr.lang
+++ b/lang/ilias_hr.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#Activity ID###04 06 2021 new variable
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.###04 06 2021 new variable
lti#:#auth_lti#:#LTI Auth
lti#:#conf_privacy_ident#:#User identification###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###26 08 2024 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
@@ -11378,7 +11376,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Autentifikacija nije uspjela, nije dan valjani potrošački ključ.
lti#:#lti_con_content_item#:#Support for Deep Linking###26 08 2024 new variable
lti#:#lti_con_content_item_url#:#Content URL###26 08 2024 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###26 08 2024 new variable
lti#:#lti_con_key_type#:#Public Key Type###26 08 2024 new variable
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users###
lti#:#lti_cron_title#:#LTI izlazna usluga
lti#:#lti_cron_title_desc#:#Sinkronizira napredak učenja LTI korisnika s LTI potrošačem, ako podržava izlaznu uslugu. Ovaj cron job potreban je samo za prijenos ažuriranja statusa nakon ažuriranja postavki napretka učenja.
lti#:#lti_custom_new#:#Create Own Provider Settings###04 06 2021 new variable
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Potrošači stvoreni u Administraciji ne dopuštaju odabir sadržaja
lti#:#lti_delete_consume_provider#:#Delete Provider###04 06 2021 new variable
lti#:#lti_delete_consume_providers#:#Delete Providers###04 06 2021 new variable
lti#:#lti_delete_provider#:#Delete Provider###04 06 2021 new variable
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#Uredi LTI potrošača
lti#:#lti_exit#:#Zatvori LTI sesiju
lti#:#lti_exited#:#LTI sesija zatvorena
lti#:#lti_exited_info#:#LTI sesija je uspješno zatvorena
+lti#:#lti_form_provider_content_selection#:#Odabir sadržaja
lti#:#lti_form_provider_create#:#Create Provider Settings###04 06 2021 new variable
lti#:#lti_form_provider_edit#:#Edit Provider Settings###04 06 2021 new variable
lti#:#lti_form_section_appearance#:#Options for launch###04 06 2021 new variable
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#Certificate###04 06 2021 new variable
lti#:#subtab_object_settings#:#Object Settings###04 06 2021 new variable
lti#:#subtab_provider_settings#:#LTI Provider Settings###04 06 2021 new variable
lti#:#tab_content#:#Content###04 06 2021 new variable
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info###04 06 2021 new variable
lti#:#tab_scoring#:#Ranking###04 06 2021 new variable
lti#:#tab_settings#:#Settings###04 06 2021 new variable
diff --git a/lang/ilias_hu.lang b/lang/ilias_hu.lang
index cd95046ca96b..cd173031f2fe 100644
--- a/lang/ilias_hu.lang
+++ b/lang/ilias_hu.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#AktivításID
lti#:#activity_id_info#:#Ezt az AktivításID-t használja az LTI Kiszolgáló, hogy azonosítsa a Statement-eket.
lti#:#auth_lti#:#LTI-hitelesítés
lti#:#conf_privacy_ident#:#Felhasználói azonosítás
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash és az egyedi ILIAS platform_id e-mail cím formátumban.
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#Ez azonosítja az összes hívást, de nem lehet belőle következtetni felhasználóra.
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash és az egyedi ILIAS platform_id e-mail cím formátumban.
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#Ez azonosítja az összes hívást, de nem lehet belőle következtetni felhasználóra.
lti#:#conf_privacy_ident_il_uuid_ext_account#:#A külső user_id és az egyedi ILIAS platform_id e-mail cím formátumban.
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#Ez azonosítja az összes hívást, de esetleg következtetni enged a felhasználóra.
lti#:#conf_privacy_ident_il_uuid_login#:#Az ILIAS felhasználónév és az egyedi ILIAS platform_id e-mail cím formátumban.
lti#:#conf_privacy_ident_il_uuid_login_info#:#A felhasználónevet küldjük. Ez azonosítja az összes hívást, de esetleg következtetni enged az ILIAS felhasználóra.
lti#:#conf_privacy_ident_il_uuid_random#:#Véletlen id és az egyedi ILIAS platform_id e-mail cím formátumban.
lti#:#conf_privacy_ident_il_uuid_random_info#:#Az összes ILIAS objektum és az összes ILIAS felhasználó számára egy véletlen azonosítót generálunk minden híváskor, így a felhasználóval kapcsolatos következtetések nagyon korlátozottak lesznek, mert gyakorlatilag lehetetlen objektumokra hivatkozó felhasználói profilokat létrehozni.
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash és az egyedi ILIAS platform_id e-mail cím formátumban.
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#Ez azonosítja az összes hívást, de nem lehet belőle következtetni felhasználóra.
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash és az egyedi ILIAS domainnel e-mail cím formátumban.
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#Ez azonosítja az összes hívást, legfeljebb 80 karakterrel lényegesen rövidebb, mint az ILIAS platformazonosítójú változat, és csak nagyon korlátozott következtetéseket tesz lehetővé a felhasználóról.
lti#:#conf_privacy_ident_il_uuid_user_id#:#Az ILIAS user_id és az egyedi ILIAS platform_id e-mail cím formátumban.
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#LTI-felhasználónak ajánlott globális szerep
lti#:#lti_cron_title#:#LTI-kimeneti Szolgáltatás
lti#:#lti_cron_title_desc#:#Az LTI-felhasználók tanulási haladási állapotát szinkronizálja egy LTI-eszközfogyasztóval, amennyiben az támogatja a kimeneti szolgáltatást. Erre az ütemezett feladatra csak a tanulási haladás beállításainak módosítása után van szükség.
lti#:#lti_custom_new#:#Create Own Settings for Provider resp. Tool
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Az Adminisztrációban létrehozott fogyasztók nem teszik lehetővé a tartalom kiválasztását
lti#:#lti_delete_consume_provider#:#Kiszolgáló törlése
lti#:#lti_delete_consume_providers#:# Kiszolgálók törlése
lti#:#lti_delete_provider#:#Kiszolgáló törlése
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#LTI-fogyasztó módosítása
lti#:#lti_exit#:#LTI-munkamenet lezárása
lti#:#lti_exited#:#LTI-munkamenet lezárva
lti#:#lti_exited_info#:#LTI-munkamenet sikeresen lezárult
+lti#:#lti_form_provider_content_selection#:#Tartalom kiválasztása
lti#:#lti_form_provider_create#:#Kiszolgáló beállításainak létrehozása
lti#:#lti_form_provider_edit#:#Kiszolgáló beállításainak módosítása
lti#:#lti_form_section_appearance#:#Indítás beállításai
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#Tanúsítványok
lti#:#subtab_object_settings#:#Objektum beállításai
lti#:#subtab_provider_settings#:#Kiszolgáló resp. Eszköz beállításai
lti#:#tab_content#:#Tartalom
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info
lti#:#tab_scoring#:#Helyezés
lti#:#tab_settings#:#Beállítások
@@ -18059,4 +18060,4 @@ wsp#:#wsp_type_ltiv#:#Tanúsítvány: LTI-Fogyasztók
wsp#:#wsp_type_scov#:#Tanúsítvány: SCORM
wsp#:#wsp_type_tstv#:#Tanúsítvány: teszt
wsp#:#wsp_type_webr#:#Weblink
-wsp#:#wsp_type_wfld#:#Mappa
\ No newline at end of file
+wsp#:#wsp_type_wfld#:#Mappa
diff --git a/lang/ilias_it.lang b/lang/ilias_it.lang
index d001a074d4ca..73e8b38b69c2 100644
--- a/lang/ilias_it.lang
+++ b/lang/ilias_it.lang
@@ -11257,16 +11257,14 @@ lti#:#activity_id#:#ID attività
lti#:#activity_id_info#:#Questo ID attività viene utilizzato dal provider LTI per identificare gli statements.
lti#:#auth_lti#:#Auth LTI
lti#:#conf_privacy_ident#:#User identification###28 11 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###28 11 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###28 11 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###28 11 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###28 11 2025 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###28 11 2025 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###28 11 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###28 11 2025 new variable
@@ -11377,8 +11375,8 @@ lti#:#lti_at_least_one_prov_has_usages#:#Almeno uno dei provider non può essere
lti#:#lti_auth_failed_invalid_key#:#Autenticazione fallita, nessuna chiave del consumatore valida fornita.
lti#:#lti_con_content_item#:#Support for Deep Linking###31 03 2023 new variable
lti#:#lti_con_content_item_url#:#Content URL###31 03 2023 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
-lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization_info#:#Lo strumento LTI deve offrire 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###31 03 2023 new variable
lti#:#lti_con_key_type#:#Public Key Type###31 03 2023 new variable
lti#:#lti_con_key_type_jwk#:#URL (Json Web Token)###31 03 2023 new variable
@@ -11467,6 +11465,7 @@ lti#:#lti_create_lti_user_role#:#Crea un ruolo globale raccomandato per gli uten
lti#:#lti_cron_title#:#Servizio esiti LTI
lti#:#lti_cron_title_desc#:#Sincronizza i progressi didattici degli utenti LTI con i consumatori LTI, se supporta il servizio degli esiti. Questo cron job è richiesto solo per trasferire aggiornamenti di stato dopo l'aggiornamento dei settaggi dei progressi didattici.
lti#:#lti_custom_new#:#Impostazioni di creazione fornitore personale
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#I consumer creati in Amministrazione non consentono la selezione del contenuto
lti#:#lti_delete_consume_provider#:#Elimina fornitore
lti#:#lti_delete_consume_providers#:#Elimina fornitori
lti#:#lti_delete_provider#:#Elimina fornitore
@@ -11475,6 +11474,7 @@ lti#:#lti_edit_consumer#:#Modifica consumatore LTI
lti#:#lti_exit#:#Chiudi sessione LTI
lti#:#lti_exited#:#Sessione LTI chiusa
lti#:#lti_exited_info#:#Sessione LTI chiusa con successo
+lti#:#lti_form_provider_content_selection#:#Selezione contenuto
lti#:#lti_form_provider_create#:#Impostazioni di creazione fornitore
lti#:#lti_form_provider_edit#:#Modifica impostazioni del fornitore
lti#:#lti_form_section_appearance#:#Opzioni di avvio
@@ -11526,6 +11526,7 @@ lti#:#subtab_certificate#:#Certificato
lti#:#subtab_object_settings#:#Impostazioni oggetto
lti#:#subtab_provider_settings#:#Impostazioni fornitore LTI
lti#:#tab_content#:#Contenuto
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info
lti#:#tab_scoring#:#Classifica
lti#:#tab_settings#:#Impostazioni
diff --git a/lang/ilias_ja.lang b/lang/ilias_ja.lang
index f2d7bb046525..ce6dda4e9553 100644
--- a/lang/ilias_ja.lang
+++ b/lang/ilias_ja.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#アクティビティID
lti#:#activity_id_info#:#このアクティビティIDはステートメント識別用にLTIプロバイダが使用します。
lti#:#auth_lti#:#LTI Auth
lti#:#conf_privacy_ident#:#ユーザID
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#ハッシュは、Eメールアドレス形式でフォーマットされたユニークなILIASプラットフォームIDと組み合わされます
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#これは各呼び出しと同一ですが、ILIASユーザーについての直接的な結論を許しません。
+lti#:#conf_privacy_ident_il_uuid_sha256#:#ハッシュと、Eメールアドレスとして形式化されたユニークなILIASプラットフォームIDを組み合わせたもの
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#これはコール毎に同じですが、ILIASユーザに関してはダイレクトに終結は許可されません。
lti#:#conf_privacy_ident_il_uuid_ext_account#:#Eメールアドレス用にユニークなILIASプラットフォームでフォーマットされて組み合された外部ユーザID
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#これはコール毎に同じですが、ユーザに関してはダイレクトに終結する事があります。
lti#:#conf_privacy_ident_il_uuid_login#:#EメールアドレスでユニークなILIASプラットフォームでフォーマットされて組み合されたILIASログイン
lti#:#conf_privacy_ident_il_uuid_login_info#:#ログイン名を送信。これはコール毎に同じですが、ILIASユーザに関してはダイレクトに終結することがあります。
lti#:#conf_privacy_ident_il_uuid_random#:#EメールアドレスでユニークなILIASプラットフォームでフォーマットされて組み合されたランダムID
lti#:#conf_privacy_ident_il_uuid_random_info#:#それぞれILIASオブジェクトとILIASユーザランダムIDは、コール毎に同一のままのランダムIDを生成します。オブジェクトを超えたユーザプロファイル生成がほぼ不可能でる事によりユーザに関する結論は、極めて限定的です。
-lti#:#conf_privacy_ident_il_uuid_sha256#:#ハッシュと、Eメールアドレスとして形式化されたユニークなILIASプラットフォームIDを組み合わせたもの
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#これはコール毎に同じですが、ILIASユーザに関してはダイレクトに終結は許可されません。
lti#:#conf_privacy_ident_il_uuid_sha256url#:#EメールアドレスのILIASドメインでフォーマットされたハッシュ
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#これはコール毎に同じILIASプラットホームIDで可変の最高80文字よりかなり短く、ILIASユーザーに関して非常に限定された結果のみを許容。
lti#:#conf_privacy_ident_il_uuid_user_id#:#EメールアドレスでユニークなILIASプラットフォームでフォーマットされて組み合されたILIASユーザ
@@ -11378,8 +11376,8 @@ lti#:#lti_at_least_one_prov_has_usages#:# 一つ以上にこのプロバイダ
lti#:#lti_auth_failed_invalid_key#:#有効なconsumer keyがないので認証を失敗しました。
lti#:#lti_con_content_item#:#ディープリンクのサポート
lti#:#lti_con_content_item_url#:#Content URL
-lti#:#lti_con_grade_synchronization#:#拡張評価サービス
-lti#:#lti_con_grade_synchronization_info#:#LTIツールは'割当と評価サービス'を提示する必要があります。
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services
+lti#:#lti_con_grade_synchronization_info#:#LTIツールは'Assignment and Grade Services'を提供する必要があります。
lti#:#lti_con_initiate_login_url#:#Login URLを起動
lti#:#lti_con_key_type#:#Public Key Type
lti#:#lti_con_key_type_jwk#:#URL (Json Web Token)
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#LTI ユーザ用の推奨グローバル役割
lti#:#lti_cron_title#:#LTI Outcome Service
lti#:#lti_cron_title_desc#:#結果サービスをサポートしてる場合、LTI consumerでLTIユーザの学習進捗を同期します。このcron jobは学習進捗設定更新の後でステータス更新を送信する事が必須となります。
lti#:#lti_custom_new#:#自身のプロバイダー設定を作成
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#管理画面で作成されたコンシューマーではコンテンツを選択できません
lti#:#lti_delete_consume_provider#:#プロバイダーを削除
lti#:#lti_delete_consume_providers#:#プロバイダーを削除
lti#:#lti_delete_provider#:#プロバイダーを削除
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#LTI Consumerを編集
lti#:#lti_exit#:#LTI Sessionをクローズ
lti#:#lti_exited#:#LTI セッションをクローズしました
lti#:#lti_exited_info#:#LTIセッションは正しくクローズしました
+lti#:#lti_form_provider_content_selection#:#コンテンツ選択
lti#:#lti_form_provider_create#:#プロバイダー設定を作成
lti#:#lti_form_provider_edit#:#プロバイダー設定を編集
lti#:#lti_form_section_appearance#:#起動のオプション
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#履修状況
lti#:#subtab_object_settings#:#オブジェクト設定
lti#:#subtab_provider_settings#:#LTI Provider設定
lti#:#tab_content#:#コンテンツ
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info
lti#:#tab_scoring#:#ランキング
lti#:#tab_settings#:#設定
diff --git a/lang/ilias_ka.lang b/lang/ilias_ka.lang
index 291f32b4fdfe..97799832140b 100644
--- a/lang/ilias_ka.lang
+++ b/lang/ilias_ka.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#Activity ID###07 02 2020 new variable
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.###07 02 2020 new variable
lti#:#auth_lti#:#LTI Auth###31 08 2017 new variable
lti#:#conf_privacy_ident#:#User identification###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###26 08 2024 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
@@ -11378,7 +11376,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Authentication failed, no valid consumer key given.###31 08 2017 new variable
lti#:#lti_con_content_item#:#Support for Deep Linking###26 08 2024 new variable
lti#:#lti_con_content_item_url#:#Content URL###26 08 2024 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###26 08 2024 new variable
lti#:#lti_con_key_type#:#Public Key Type###26 08 2024 new variable
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users###
lti#:#lti_cron_title#:#LTI Outcome Service###07 02 2020 new variable
lti#:#lti_cron_title_desc#:#Synchronizes the learning progress of LTI users with the LTI consumer, if it supports the outcome service. This cron job is only required to transfer status updates after Learning progress settings updates.###07 02 2020 new variable
lti#:#lti_custom_new#:#Create Own Provider Settings###07 02 2020 new variable
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Consumers created in Administration do not allow content selection
lti#:#lti_delete_consume_provider#:#Delete Provider###07 02 2020 new variable
lti#:#lti_delete_consume_providers#:#Delete Providers###07 02 2020 new variable
lti#:#lti_delete_provider#:#Delete Provider###07 02 2020 new variable
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#Edit LTI Consumer###31 08 2017 new variable
lti#:#lti_exit#:#Close LTI Session###31 08 2017 new variable
lti#:#lti_exited#:#LTI Session closed###31 08 2017 new variable
lti#:#lti_exited_info#:#LTI Session successfully closed###31 08 2017 new variable
+lti#:#lti_form_provider_content_selection#:#შინაარსის არჩევა
lti#:#lti_form_provider_create#:#Create Provider Settings###07 02 2020 new variable
lti#:#lti_form_provider_edit#:#Edit Provider Settings###07 02 2020 new variable
lti#:#lti_form_section_appearance#:#Options for launch###07 02 2020 new variable
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#Certificate###07 02 2020 new variable
lti#:#subtab_object_settings#:#Object Settings###07 02 2020 new variable
lti#:#subtab_provider_settings#:#LTI Provider Settings###07 02 2020 new variable
lti#:#tab_content#:#Content###07 02 2020 new variable
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info###07 02 2020 new variable
lti#:#tab_scoring#:#Ranking###07 02 2020 new variable
lti#:#tab_settings#:#Settings###07 02 2020 new variable
diff --git a/lang/ilias_lt.lang b/lang/ilias_lt.lang
index fe3ddc2fd07c..564be009a851 100644
--- a/lang/ilias_lt.lang
+++ b/lang/ilias_lt.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#Activity ID###07 02 2020 new variable
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.###07 02 2020 new variable
lti#:#auth_lti#:#LTI Auth###31 08 2017 new variable
lti#:#conf_privacy_ident#:#User identification###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###26 08 2024 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
@@ -11378,7 +11376,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Authentication failed, no valid consumer key given.###31 08 2017 new variable
lti#:#lti_con_content_item#:#Support for Deep Linking###26 08 2024 new variable
lti#:#lti_con_content_item_url#:#Content URL###26 08 2024 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###26 08 2024 new variable
lti#:#lti_con_key_type#:#Public Key Type###26 08 2024 new variable
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users###
lti#:#lti_cron_title#:#LTI Outcome Service###07 02 2020 new variable
lti#:#lti_cron_title_desc#:#Synchronizes the learning progress of LTI users with the LTI consumer, if it supports the outcome service. This cron job is only required to transfer status updates after Learning progress settings updates.###07 02 2020 new variable
lti#:#lti_custom_new#:#Create Own Provider Settings###07 02 2020 new variable
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Consumers created in Administration do not allow content selection
lti#:#lti_delete_consume_provider#:#Delete Provider###07 02 2020 new variable
lti#:#lti_delete_consume_providers#:#Delete Providers###07 02 2020 new variable
lti#:#lti_delete_provider#:#Delete Provider###07 02 2020 new variable
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#Edit LTI Consumer###31 08 2017 new variable
lti#:#lti_exit#:#Close LTI Session###31 08 2017 new variable
lti#:#lti_exited#:#LTI Session closed###31 08 2017 new variable
lti#:#lti_exited_info#:#LTI Session successfully closed###31 08 2017 new variable
+lti#:#lti_form_provider_content_selection#:#Turinio pasirinkimas
lti#:#lti_form_provider_create#:#Create Provider Settings###07 02 2020 new variable
lti#:#lti_form_provider_edit#:#Edit Provider Settings###07 02 2020 new variable
lti#:#lti_form_section_appearance#:#Options for launch###07 02 2020 new variable
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#Certificate###07 02 2020 new variable
lti#:#subtab_object_settings#:#Object Settings###07 02 2020 new variable
lti#:#subtab_provider_settings#:#LTI Provider Settings###07 02 2020 new variable
lti#:#tab_content#:#Content###07 02 2020 new variable
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info###07 02 2020 new variable
lti#:#tab_scoring#:#Ranking###07 02 2020 new variable
lti#:#tab_settings#:#Settings###07 02 2020 new variable
diff --git a/lang/ilias_nl.lang b/lang/ilias_nl.lang
index 7541e5376e73..a3e15bcbe39b 100644
--- a/lang/ilias_nl.lang
+++ b/lang/ilias_nl.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#Activity ID###07 02 2020 new variable
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.###07 02 2020 new variable
lti#:#auth_lti#:#LTI Auth###31 08 2017 new variable
lti#:#conf_privacy_ident#:#User identification###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###26 08 2024 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
@@ -11378,7 +11376,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Authentication failed, no valid consumer key given.###31 08 2017 new variable
lti#:#lti_con_content_item#:#Support for Deep Linking###26 08 2024 new variable
lti#:#lti_con_content_item_url#:#Content URL###26 08 2024 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###26 08 2024 new variable
lti#:#lti_con_key_type#:#Public Key Type###26 08 2024 new variable
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users###
lti#:#lti_cron_title#:#LTI Outcome Service###07 02 2020 new variable
lti#:#lti_cron_title_desc#:#Synchronizes the learning progress of LTI users with the LTI consumer, if it supports the outcome service. This cron job is only required to transfer status updates after Learning progress settings updates.###07 02 2020 new variable
lti#:#lti_custom_new#:#Create Own Provider Settings###07 02 2020 new variable
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Consumers created in Administration do not allow content selection
lti#:#lti_delete_consume_provider#:#Delete Provider###07 02 2020 new variable
lti#:#lti_delete_consume_providers#:#Delete Providers###07 02 2020 new variable
lti#:#lti_delete_provider#:#Delete Provider###07 02 2020 new variable
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#Edit LTI Consumer###31 08 2017 new variable
lti#:#lti_exit#:#Close LTI Session###31 08 2017 new variable
lti#:#lti_exited#:#LTI Session closed###31 08 2017 new variable
lti#:#lti_exited_info#:#LTI Session successfully closed###31 08 2017 new variable
+lti#:#lti_form_provider_content_selection#:#Inhoud selecteren
lti#:#lti_form_provider_create#:#Create Provider Settings###07 02 2020 new variable
lti#:#lti_form_provider_edit#:#Edit Provider Settings###07 02 2020 new variable
lti#:#lti_form_section_appearance#:#Options for launch###07 02 2020 new variable
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#Certificate###07 02 2020 new variable
lti#:#subtab_object_settings#:#Object Settings###07 02 2020 new variable
lti#:#subtab_provider_settings#:#LTI Provider Settings###07 02 2020 new variable
lti#:#tab_content#:#Content###07 02 2020 new variable
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info###07 02 2020 new variable
lti#:#tab_scoring#:#Ranking###07 02 2020 new variable
lti#:#tab_settings#:#Settings###07 02 2020 new variable
diff --git a/lang/ilias_pl.lang b/lang/ilias_pl.lang
index 76009f037d6f..2a0c5fa7607e 100644
--- a/lang/ilias_pl.lang
+++ b/lang/ilias_pl.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#Activity ID###07 02 2020 new variable
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.###07 02 2020 new variable
lti#:#auth_lti#:#LTI Auth
lti#:#conf_privacy_ident#:#User identification###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###26 08 2024 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
@@ -11378,7 +11376,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Identyfikacja nie jest możliwa. Nie przekazano ważnego klucza odbiorcy.
lti#:#lti_con_content_item#:#Support for Deep Linking###26 08 2024 new variable
lti#:#lti_con_content_item_url#:#Content URL###26 08 2024 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###26 08 2024 new variable
lti#:#lti_con_key_type#:#Public Key Type###26 08 2024 new variable
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users###
lti#:#lti_cron_title#:#LTI Outcome Service###07 02 2020 new variable
lti#:#lti_cron_title_desc#:#Synchronizes the learning progress of LTI users with the LTI consumer, if it supports the outcome service. This cron job is only required to transfer status updates after Learning progress settings updates.###07 02 2020 new variable
lti#:#lti_custom_new#:#Create Own Provider Settings###07 02 2020 new variable
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Konsumenci utworzeni w Administracji nie pozwalają na wybór treści
lti#:#lti_delete_consume_provider#:#Delete Provider###07 02 2020 new variable
lti#:#lti_delete_consume_providers#:#Delete Providers###07 02 2020 new variable
lti#:#lti_delete_provider#:#Delete Provider###07 02 2020 new variable
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#Edytuj odbiorcę LTI
lti#:#lti_exit#:#Zakończ sesję LTI
lti#:#lti_exited#:#Sesja LTI zakończona
lti#:#lti_exited_info#:#Udało się zakończyć sesję LTI
+lti#:#lti_form_provider_content_selection#:#Wybór treści
lti#:#lti_form_provider_create#:#Create Provider Settings###07 02 2020 new variable
lti#:#lti_form_provider_edit#:#Edit Provider Settings###07 02 2020 new variable
lti#:#lti_form_section_appearance#:#Options for launch###07 02 2020 new variable
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#Certificate###07 02 2020 new variable
lti#:#subtab_object_settings#:#Object Settings###07 02 2020 new variable
lti#:#subtab_provider_settings#:#LTI Provider Settings###07 02 2020 new variable
lti#:#tab_content#:#Content###07 02 2020 new variable
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info###07 02 2020 new variable
lti#:#tab_scoring#:#Ranking###07 02 2020 new variable
lti#:#tab_settings#:#Settings###07 02 2020 new variable
diff --git a/lang/ilias_pt.lang b/lang/ilias_pt.lang
index 392f768dd10b..861a4b4b8173 100644
--- a/lang/ilias_pt.lang
+++ b/lang/ilias_pt.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#Activity ID###07 02 2020 new variable
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.###07 02 2020 new variable
lti#:#auth_lti#:#LTI Aut
lti#:#conf_privacy_ident#:#User identification###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###26 08 2024 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
@@ -11378,7 +11376,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Autenticação falhou, nenhuma chave de consumidor fornecida.
lti#:#lti_con_content_item#:#Support for Deep Linking###26 08 2024 new variable
lti#:#lti_con_content_item_url#:#Content URL###26 08 2024 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###26 08 2024 new variable
lti#:#lti_con_key_type#:#Public Key Type###26 08 2024 new variable
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users###
lti#:#lti_cron_title#:#Autoavaliação
lti#:#lti_cron_title_desc#:#Densidade semântica
lti#:#lti_custom_new#:#Create Own Provider Settings###07 02 2020 new variable
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Consumidores criados na Administração não permitem a seleção de conteúdo
lti#:#lti_delete_consume_provider#:#Delete Provider###07 02 2020 new variable
lti#:#lti_delete_consume_providers#:#Delete Providers###07 02 2020 new variable
lti#:#lti_delete_provider#:#Delete Provider###07 02 2020 new variable
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#Editar consumidor LIT
lti#:#lti_exit#:#Fechar sessão LTI
lti#:#lti_exited#:#Sessão LTI fechada
lti#:#lti_exited_info#:#Sessão LTI fechada com sucesso
+lti#:#lti_form_provider_content_selection#:#Seleção de conteúdo
lti#:#lti_form_provider_create#:#Create Provider Settings###07 02 2020 new variable
lti#:#lti_form_provider_edit#:#Edit Provider Settings###07 02 2020 new variable
lti#:#lti_form_section_appearance#:#Options for launch###07 02 2020 new variable
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#Certificate###07 02 2020 new variable
lti#:#subtab_object_settings#:#Object Settings###07 02 2020 new variable
lti#:#subtab_provider_settings#:#LTI Provider Settings###07 02 2020 new variable
lti#:#tab_content#:#Content###07 02 2020 new variable
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info###07 02 2020 new variable
lti#:#tab_scoring#:#Ranking###07 02 2020 new variable
lti#:#tab_settings#:#Settings###07 02 2020 new variable
diff --git a/lang/ilias_ro.lang b/lang/ilias_ro.lang
index 694f49c88ac5..c7174cfa2921 100644
--- a/lang/ilias_ro.lang
+++ b/lang/ilias_ro.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#Activity ID###07 02 2020 new variable
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.###07 02 2020 new variable
lti#:#auth_lti#:#LTI Auth###31 08 2017 new variable
lti#:#conf_privacy_ident#:#User identification###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###26 08 2024 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
@@ -11378,7 +11376,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Authentication failed, no valid consumer key given.###31 08 2017 new variable
lti#:#lti_con_content_item#:#Support for Deep Linking###26 08 2024 new variable
lti#:#lti_con_content_item_url#:#Content URL###26 08 2024 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###26 08 2024 new variable
lti#:#lti_con_key_type#:#Public Key Type###26 08 2024 new variable
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users###
lti#:#lti_cron_title#:#LTI Outcome Service###07 02 2020 new variable
lti#:#lti_cron_title_desc#:#Synchronizes the learning progress of LTI users with the LTI consumer, if it supports the outcome service. This cron job is only required to transfer status updates after Learning progress settings updates.###07 02 2020 new variable
lti#:#lti_custom_new#:#Create Own Provider Settings###07 02 2020 new variable
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Consumers created in Administration do not allow content selection
lti#:#lti_delete_consume_provider#:#Delete Provider###07 02 2020 new variable
lti#:#lti_delete_consume_providers#:#Delete Providers###07 02 2020 new variable
lti#:#lti_delete_provider#:#Delete Provider###07 02 2020 new variable
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#Edit LTI Consumer###31 08 2017 new variable
lti#:#lti_exit#:#Close LTI Session###31 08 2017 new variable
lti#:#lti_exited#:#LTI Session closed###31 08 2017 new variable
lti#:#lti_exited_info#:#LTI Session successfully closed###31 08 2017 new variable
+lti#:#lti_form_provider_content_selection#:#Selectarea conținutului
lti#:#lti_form_provider_create#:#Create Provider Settings###07 02 2020 new variable
lti#:#lti_form_provider_edit#:#Edit Provider Settings###07 02 2020 new variable
lti#:#lti_form_section_appearance#:#Options for launch###07 02 2020 new variable
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#Certificate###07 02 2020 new variable
lti#:#subtab_object_settings#:#Object Settings###07 02 2020 new variable
lti#:#subtab_provider_settings#:#LTI Provider Settings###07 02 2020 new variable
lti#:#tab_content#:#Content###07 02 2020 new variable
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info###07 02 2020 new variable
lti#:#tab_scoring#:#Ranking###07 02 2020 new variable
lti#:#tab_settings#:#Settings###07 02 2020 new variable
diff --git a/lang/ilias_ru.lang b/lang/ilias_ru.lang
index 8c9b860ec0f1..964f71e96805 100644
--- a/lang/ilias_ru.lang
+++ b/lang/ilias_ru.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#Activity ID###07 02 2020 new variable
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.###07 02 2020 new variable
lti#:#auth_lti#:#LTI Auth###31 08 2017 new variable
lti#:#conf_privacy_ident#:#User identification###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###26 08 2024 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
@@ -11378,7 +11376,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Authentication failed, no valid consumer key given.###31 08 2017 new variable
lti#:#lti_con_content_item#:#Support for Deep Linking###26 08 2024 new variable
lti#:#lti_con_content_item_url#:#Content URL###26 08 2024 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###26 08 2024 new variable
lti#:#lti_con_key_type#:#Public Key Type###26 08 2024 new variable
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users###
lti#:#lti_cron_title#:#LTI Outcome Service###07 02 2020 new variable
lti#:#lti_cron_title_desc#:#Synchronizes the learning progress of LTI users with the LTI consumer, if it supports the outcome service. This cron job is only required to transfer status updates after Learning progress settings updates.###07 02 2020 new variable
lti#:#lti_custom_new#:#Create Own Provider Settings###07 02 2020 new variable
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Consumers created in Administration do not allow content selection
lti#:#lti_delete_consume_provider#:#Delete Provider###07 02 2020 new variable
lti#:#lti_delete_consume_providers#:#Delete Providers###07 02 2020 new variable
lti#:#lti_delete_provider#:#Delete Provider###07 02 2020 new variable
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#Edit LTI Consumer###31 08 2017 new variable
lti#:#lti_exit#:#Close LTI Session###31 08 2017 new variable
lti#:#lti_exited#:#LTI Session closed###31 08 2017 new variable
lti#:#lti_exited_info#:#LTI Session successfully closed###31 08 2017 new variable
+lti#:#lti_form_provider_content_selection#:#Выбор содержимого
lti#:#lti_form_provider_create#:#Create Provider Settings###07 02 2020 new variable
lti#:#lti_form_provider_edit#:#Edit Provider Settings###07 02 2020 new variable
lti#:#lti_form_section_appearance#:#Options for launch###07 02 2020 new variable
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#Certificate###07 02 2020 new variable
lti#:#subtab_object_settings#:#Object Settings###07 02 2020 new variable
lti#:#subtab_provider_settings#:#LTI Provider Settings###07 02 2020 new variable
lti#:#tab_content#:#Content###07 02 2020 new variable
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info###07 02 2020 new variable
lti#:#tab_scoring#:#Ranking###07 02 2020 new variable
lti#:#tab_settings#:#Settings###07 02 2020 new variable
diff --git a/lang/ilias_sk.lang b/lang/ilias_sk.lang
index b3a78172c37b..b988a72a7505 100644
--- a/lang/ilias_sk.lang
+++ b/lang/ilias_sk.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#Activity ID###07 02 2020 new variable
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.###07 02 2020 new variable
lti#:#auth_lti#:#LTI Auth###31 08 2017 new variable
lti#:#conf_privacy_ident#:#User identification###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###26 08 2024 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
@@ -11378,7 +11376,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Authentication failed, no valid consumer key given.###31 08 2017 new variable
lti#:#lti_con_content_item#:#Support for Deep Linking###26 08 2024 new variable
lti#:#lti_con_content_item_url#:#Content URL###26 08 2024 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###26 08 2024 new variable
lti#:#lti_con_key_type#:#Public Key Type###26 08 2024 new variable
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users###
lti#:#lti_cron_title#:#LTI Outcome Service###07 02 2020 new variable
lti#:#lti_cron_title_desc#:#Synchronizes the learning progress of LTI users with the LTI consumer, if it supports the outcome service. This cron job is only required to transfer status updates after Learning progress settings updates.###07 02 2020 new variable
lti#:#lti_custom_new#:#Create Own Provider Settings###07 02 2020 new variable
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Consumers created in Administration do not allow content selection
lti#:#lti_delete_consume_provider#:#Delete Provider###07 02 2020 new variable
lti#:#lti_delete_consume_providers#:#Delete Providers###07 02 2020 new variable
lti#:#lti_delete_provider#:#Delete Provider###07 02 2020 new variable
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#Edit LTI Consumer###31 08 2017 new variable
lti#:#lti_exit#:#Close LTI Session###31 08 2017 new variable
lti#:#lti_exited#:#LTI Session closed###31 08 2017 new variable
lti#:#lti_exited_info#:#LTI Session successfully closed###31 08 2017 new variable
+lti#:#lti_form_provider_content_selection#:#Výber obsahu
lti#:#lti_form_provider_create#:#Create Provider Settings###07 02 2020 new variable
lti#:#lti_form_provider_edit#:#Edit Provider Settings###07 02 2020 new variable
lti#:#lti_form_section_appearance#:#Options for launch###07 02 2020 new variable
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#Certificate###07 02 2020 new variable
lti#:#subtab_object_settings#:#Object Settings###07 02 2020 new variable
lti#:#subtab_provider_settings#:#LTI Provider Settings###07 02 2020 new variable
lti#:#tab_content#:#Content###07 02 2020 new variable
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info###07 02 2020 new variable
lti#:#tab_scoring#:#Ranking###07 02 2020 new variable
lti#:#tab_settings#:#Settings###07 02 2020 new variable
diff --git a/lang/ilias_sl.lang b/lang/ilias_sl.lang
index 903df3c8e1b9..b82c0436f096 100644
--- a/lang/ilias_sl.lang
+++ b/lang/ilias_sl.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#Activity ID
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.
lti#:#auth_lti#:#LTI Auth
lti#:#conf_privacy_ident#:#User identification
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###20 07 2022 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###20 07 2022 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User Id combined with a unique ILIAS platform id formated as an email adress.
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formated as an email adress.
lti#:#conf_privacy_ident_il_uuid_login_info#:#This is identical to each call, but may allow a direct conclusion about the ILIAS user.
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formated as an email adress.
@@ -11378,7 +11376,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Avtentikacija ni mogoča. Noben veljaven consumer key ni bil prenesen.
lti#:#lti_con_content_item#:#Support for Deep Linking###19 08 2022 new variable
lti#:#lti_con_content_item_url#:#Content URL###19 08 2022 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###19 08 2022 new variable
lti#:#lti_con_key_type#:#Public Key Type###19 08 2022 new variable
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users
lti#:#lti_cron_title#:#LTI Outcome Service
lti#:#lti_cron_title_desc#:#Prenese učni napredek od uporabnikov LTI na platformo za priklic. Ta cron job je potreben samo v primerih, ko je treba učni napredek na novo izračunati zaradi sprememb nastavitev.
lti#:#lti_custom_new#:#Create Own Provider Settings
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Potrošniki, ustvarjeni v Administraciji, ne omogočajo izbire vsebine
lti#:#lti_delete_consume_provider#:#Delete Provider
lti#:#lti_delete_consume_providers#:#Delete Providers
lti#:#lti_delete_provider#:#Delete Provider
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#Uredi potrošnika LTI
lti#:#lti_exit#:#Zaključi sejo LTI
lti#:#lti_exited#:#Seja LTI je zaključena
lti#:#lti_exited_info#:#Seja LTI je bila uspešno zaključena
+lti#:#lti_form_provider_content_selection#:#Izbira vsebine
lti#:#lti_form_provider_create#:#Create Provider Settings
lti#:#lti_form_provider_edit#:#Edit Provider Settings
lti#:#lti_form_section_appearance#:#Options for launch
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#Certificate
lti#:#subtab_object_settings#:#Object Settings
lti#:#subtab_provider_settings#:#LTI Provider Settings
lti#:#tab_content#:#Content
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info
lti#:#tab_scoring#:#Ranking
lti#:#tab_settings#:#Settings
diff --git a/lang/ilias_sq.lang b/lang/ilias_sq.lang
index 4c3f3c162dd2..a2abd72ecde8 100644
--- a/lang/ilias_sq.lang
+++ b/lang/ilias_sq.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#Activity ID###07 02 2020 new variable
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.###07 02 2020 new variable
lti#:#auth_lti#:#LTI Auth###31 08 2017 new variable
lti#:#conf_privacy_ident#:#User identification###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###26 08 2024 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
@@ -11378,7 +11376,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Authentication failed, no valid consumer key given.###31 08 2017 new variable
lti#:#lti_con_content_item#:#Support for Deep Linking###26 08 2024 new variable
lti#:#lti_con_content_item_url#:#Content URL###26 08 2024 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###26 08 2024 new variable
lti#:#lti_con_key_type#:#Public Key Type###26 08 2024 new variable
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users###
lti#:#lti_cron_title#:#LTI Outcome Service###07 02 2020 new variable
lti#:#lti_cron_title_desc#:#Synchronizes the learning progress of LTI users with the LTI consumer, if it supports the outcome service. This cron job is only required to transfer status updates after Learning progress settings updates.###07 02 2020 new variable
lti#:#lti_custom_new#:#Create Own Provider Settings###07 02 2020 new variable
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Consumers created in Administration do not allow content selection
lti#:#lti_delete_consume_provider#:#Delete Provider###07 02 2020 new variable
lti#:#lti_delete_consume_providers#:#Delete Providers###07 02 2020 new variable
lti#:#lti_delete_provider#:#Delete Provider###07 02 2020 new variable
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#Edit LTI Consumer###31 08 2017 new variable
lti#:#lti_exit#:#Close LTI Session###31 08 2017 new variable
lti#:#lti_exited#:#LTI Session closed###31 08 2017 new variable
lti#:#lti_exited_info#:#LTI Session successfully closed###31 08 2017 new variable
+lti#:#lti_form_provider_content_selection#:#Përzgjedhja e përmbajtjes
lti#:#lti_form_provider_create#:#Create Provider Settings###07 02 2020 new variable
lti#:#lti_form_provider_edit#:#Edit Provider Settings###07 02 2020 new variable
lti#:#lti_form_section_appearance#:#Options for launch###07 02 2020 new variable
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#Certificate###07 02 2020 new variable
lti#:#subtab_object_settings#:#Object Settings###07 02 2020 new variable
lti#:#subtab_provider_settings#:#LTI Provider Settings###07 02 2020 new variable
lti#:#tab_content#:#Content###07 02 2020 new variable
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info###07 02 2020 new variable
lti#:#tab_scoring#:#Ranking###07 02 2020 new variable
lti#:#tab_settings#:#Settings###07 02 2020 new variable
diff --git a/lang/ilias_sr.lang b/lang/ilias_sr.lang
index 86821aa99ed0..ab608a99d1be 100644
--- a/lang/ilias_sr.lang
+++ b/lang/ilias_sr.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#Activity ID###07 02 2020 new variable
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.###07 02 2020 new variable
lti#:#auth_lti#:#LTI Auth###31 08 2017 new variable
lti#:#conf_privacy_ident#:#User identification###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###26 08 2024 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
@@ -11378,7 +11376,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Authentication failed, no valid consumer key given.###31 08 2017 new variable
lti#:#lti_con_content_item#:#Support for Deep Linking###26 08 2024 new variable
lti#:#lti_con_content_item_url#:#Content URL###26 08 2024 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###26 08 2024 new variable
lti#:#lti_con_key_type#:#Public Key Type###26 08 2024 new variable
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users###
lti#:#lti_cron_title#:#LTI Outcome Service###07 02 2020 new variable
lti#:#lti_cron_title_desc#:#Synchronizes the learning progress of LTI users with the LTI consumer, if it supports the outcome service. This cron job is only required to transfer status updates after Learning progress settings updates.###07 02 2020 new variable
lti#:#lti_custom_new#:#Create Own Provider Settings###07 02 2020 new variable
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Consumers created in Administration do not allow content selection
lti#:#lti_delete_consume_provider#:#Delete Provider###07 02 2020 new variable
lti#:#lti_delete_consume_providers#:#Delete Providers###07 02 2020 new variable
lti#:#lti_delete_provider#:#Delete Provider###07 02 2020 new variable
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#Edit LTI Consumer###31 08 2017 new variable
lti#:#lti_exit#:#Close LTI Session###31 08 2017 new variable
lti#:#lti_exited#:#LTI Session closed###31 08 2017 new variable
lti#:#lti_exited_info#:#LTI Session successfully closed###31 08 2017 new variable
+lti#:#lti_form_provider_content_selection#:#Izbor sadržaja
lti#:#lti_form_provider_create#:#Create Provider Settings###07 02 2020 new variable
lti#:#lti_form_provider_edit#:#Edit Provider Settings###07 02 2020 new variable
lti#:#lti_form_section_appearance#:#Options for launch###07 02 2020 new variable
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#Certificate###07 02 2020 new variable
lti#:#subtab_object_settings#:#Object Settings###07 02 2020 new variable
lti#:#subtab_provider_settings#:#LTI Provider Settings###07 02 2020 new variable
lti#:#tab_content#:#Content###07 02 2020 new variable
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info###07 02 2020 new variable
lti#:#tab_scoring#:#Ranking###07 02 2020 new variable
lti#:#tab_settings#:#Settings###07 02 2020 new variable
diff --git a/lang/ilias_sv.lang b/lang/ilias_sv.lang
index 334920987bb7..bdba9d3d78e7 100644
--- a/lang/ilias_sv.lang
+++ b/lang/ilias_sv.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#Aktivitets-ID
lti#:#activity_id_info#:#Detta aktivitets-ID används av LTI-leverantören eller verktyget för att identifiera uttalanden.
lti#:#auth_lti#:#LTI Auth
lti#:#conf_privacy_ident#:#Identifiering av användare
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###21 11 2023 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###21 11 2023 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#Externt användar-ID kombinerat med ett unikt ILIAS-plattforms-ID formaterat som en e-postadress.
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#Detta är identiskt med varje samtal, men kan göra det möjligt att dra direkta slutsatser om användaren.
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS-inloggning som e-postadress, kombinerat med ett unikt ILIAS-plattforms-ID om så krävs.
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sänder inloggningsnamnet. Detta är identiskt med varje anrop, men kan tillåta direkta slutsatser till ILIAS-användaren.
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ID för ILIAS-kontot kombinerat med ett unikt ILIAS-plattforms-ID formaterat som en e-postadress.
@@ -11378,7 +11376,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#Minst en leverantör eller ett verktyg
lti#:#lti_auth_failed_invalid_key#:#Autentisering inte möjlig. Ingen giltig konsumentnyckel överfördes.
lti#:#lti_con_content_item#:#Stöd för djuplänkning
lti#:#lti_con_content_item_url#:#URL för innehåll
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiera inloggnings-URL
lti#:#lti_con_key_type#:#Typ av den offentliga nyckeln
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#Skapa rekommenderad global roll för LTI-använ
lti#:#lti_cron_title#:#LTI Utfallstjänst
lti#:#lti_cron_title_desc#:#Överför LTI-användarnas inlärningsförlopp till den anropande plattformen. Detta cron-jobb behövs endast i de fall då inlärningsförloppet måste räknas om på grund av ändrade inställningar.
lti#:#lti_custom_new#:#Skapa din egen leverantör eller verktygsinställningar
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Konsumenter som skapats i Administration tillåter inte val av innehåll
lti#:#lti_delete_consume_provider#:#Ta bort leverantör eller verktyg
lti#:#lti_delete_consume_providers#:#Ta bort leverantör eller verktyg
lti#:#lti_delete_provider#:#Ta bort leverantör eller verktyg
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#Edit LTI konsument
lti#:#lti_exit#:#Avsluta LTI-session
lti#:#lti_exited#:#LTI-sessionen avslutad
lti#:#lti_exited_info#:#LTI-sessionen slutfördes framgångsrikt.
+lti#:#lti_form_provider_content_selection#:#Innehållsval
lti#:#lti_form_provider_create#:#Skapa inställningar för en leverantör eller ett verktyg
lti#:#lti_form_provider_edit#:#Redigera inställningar för leverantören eller verktyget
lti#:#lti_form_section_appearance#:#Alternativ för lanseringen
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#Certifikat
lti#:#subtab_object_settings#:#Inställningar för objekt
lti#:#subtab_provider_settings#:#Inställningar för leverantör eller verktyg
lti#:#tab_content#:#Innehåll
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info
lti#:#tab_scoring#:#Placeringar
lti#:#tab_settings#:#Inställningar
diff --git a/lang/ilias_tr.lang b/lang/ilias_tr.lang
index d0a8c8ea351a..a989c23f62d3 100644
--- a/lang/ilias_tr.lang
+++ b/lang/ilias_tr.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#Activity ID###07 02 2020 new variable
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.###07 02 2020 new variable
lti#:#auth_lti#:#LTI Auth###31 08 2017 new variable
lti#:#conf_privacy_ident#:#User identification###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###26 08 2024 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
@@ -11378,7 +11376,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Authentication failed, no valid consumer key given.###31 08 2017 new variable
lti#:#lti_con_content_item#:#Support for Deep Linking###26 08 2024 new variable
lti#:#lti_con_content_item_url#:#Content URL###26 08 2024 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###26 08 2024 new variable
lti#:#lti_con_key_type#:#Public Key Type###26 08 2024 new variable
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users###
lti#:#lti_cron_title#:#LTI Outcome Service###07 02 2020 new variable
lti#:#lti_cron_title_desc#:#Synchronizes the learning progress of LTI users with the LTI consumer, if it supports the outcome service. This cron job is only required to transfer status updates after Learning progress settings updates.###07 02 2020 new variable
lti#:#lti_custom_new#:#Create Own Provider Settings###07 02 2020 new variable
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Consumers created in Administration do not allow content selection
lti#:#lti_delete_consume_provider#:#Delete Provider###07 02 2020 new variable
lti#:#lti_delete_consume_providers#:#Delete Providers###07 02 2020 new variable
lti#:#lti_delete_provider#:#Delete Provider###07 02 2020 new variable
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#Edit LTI Consumer###31 08 2017 new variable
lti#:#lti_exit#:#Close LTI Session###31 08 2017 new variable
lti#:#lti_exited#:#LTI Session closed###31 08 2017 new variable
lti#:#lti_exited_info#:#LTI Session successfully closed###31 08 2017 new variable
+lti#:#lti_form_provider_content_selection#:#İçerik seçimi
lti#:#lti_form_provider_create#:#Create Provider Settings###07 02 2020 new variable
lti#:#lti_form_provider_edit#:#Edit Provider Settings###07 02 2020 new variable
lti#:#lti_form_section_appearance#:#Options for launch###07 02 2020 new variable
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#Certificate###07 02 2020 new variable
lti#:#subtab_object_settings#:#Object Settings###07 02 2020 new variable
lti#:#subtab_provider_settings#:#LTI Provider Settings###07 02 2020 new variable
lti#:#tab_content#:#Content###07 02 2020 new variable
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info###07 02 2020 new variable
lti#:#tab_scoring#:#Ranking###07 02 2020 new variable
lti#:#tab_settings#:#Settings###07 02 2020 new variable
diff --git a/lang/ilias_uk.lang b/lang/ilias_uk.lang
index f6e0b5386e5c..f06299c8ec25 100644
--- a/lang/ilias_uk.lang
+++ b/lang/ilias_uk.lang
@@ -11258,16 +11258,14 @@ lti#:#activity_id#:#Activity ID###07 02 2020 new variable
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.###07 02 2020 new variable
lti#:#auth_lti#:#LTI Auth###31 08 2017 new variable
lti#:#conf_privacy_ident#:#User identification###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###26 08 2024 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
@@ -11378,7 +11376,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Authentication failed, no valid consumer key given.###31 08 2017 new variable
lti#:#lti_con_content_item#:#Support for Deep Linking###26 08 2024 new variable
lti#:#lti_con_content_item_url#:#Content URL###26 08 2024 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###26 08 2024 new variable
lti#:#lti_con_key_type#:#Public Key Type###26 08 2024 new variable
@@ -11468,6 +11466,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users###
lti#:#lti_cron_title#:#LTI Outcome Service###07 02 2020 new variable
lti#:#lti_cron_title_desc#:#Synchronizes the learning progress of LTI users with the LTI consumer, if it supports the outcome service. This cron job is only required to transfer status updates after Learning progress settings updates.###07 02 2020 new variable
lti#:#lti_custom_new#:#Create Own Provider Settings###07 02 2020 new variable
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Consumers created in Administration do not allow content selection
lti#:#lti_delete_consume_provider#:#Delete Provider###07 02 2020 new variable
lti#:#lti_delete_consume_providers#:#Delete Providers###07 02 2020 new variable
lti#:#lti_delete_provider#:#Delete Provider###07 02 2020 new variable
@@ -11476,6 +11475,7 @@ lti#:#lti_edit_consumer#:#Edit LTI Consumer###31 08 2017 new variable
lti#:#lti_exit#:#Close LTI Session###31 08 2017 new variable
lti#:#lti_exited#:#LTI Session closed###31 08 2017 new variable
lti#:#lti_exited_info#:#LTI Session successfully closed###31 08 2017 new variable
+lti#:#lti_form_provider_content_selection#:#Вибір вмісту
lti#:#lti_form_provider_create#:#Create Provider Settings###07 02 2020 new variable
lti#:#lti_form_provider_edit#:#Edit Provider Settings###07 02 2020 new variable
lti#:#lti_form_section_appearance#:#Options for launch###07 02 2020 new variable
@@ -11527,6 +11527,7 @@ lti#:#subtab_certificate#:#Certificate###07 02 2020 new variable
lti#:#subtab_object_settings#:#Object Settings###07 02 2020 new variable
lti#:#subtab_provider_settings#:#LTI Provider Settings###07 02 2020 new variable
lti#:#tab_content#:#Content###07 02 2020 new variable
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info###07 02 2020 new variable
lti#:#tab_scoring#:#Ranking###07 02 2020 new variable
lti#:#tab_settings#:#Settings###07 02 2020 new variable
diff --git a/lang/ilias_vi.lang b/lang/ilias_vi.lang
index 38718c93e735..a3282ab7a183 100644
--- a/lang/ilias_vi.lang
+++ b/lang/ilias_vi.lang
@@ -11260,16 +11260,14 @@ lti#:#activity_id#:#Activity ID###07 02 2020 new variable
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.###07 02 2020 new variable
lti#:#auth_lti#:#LTI Auth###31 08 2017 new variable
lti#:#conf_privacy_ident#:#User identification###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###26 08 2024 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
@@ -11380,7 +11378,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Authentication failed, no valid consumer key given.###31 08 2017 new variable
lti#:#lti_con_content_item#:#Support for Deep Linking###26 08 2024 new variable
lti#:#lti_con_content_item_url#:#Content URL###26 08 2024 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###26 08 2024 new variable
lti#:#lti_con_key_type#:#Public Key Type###26 08 2024 new variable
@@ -11470,6 +11468,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users###
lti#:#lti_cron_title#:#LTI Outcome Service###07 02 2020 new variable
lti#:#lti_cron_title_desc#:#Synchronizes the learning progress of LTI users with the LTI consumer, if it supports the outcome service. This cron job is only required to transfer status updates after Learning progress settings updates.###07 02 2020 new variable
lti#:#lti_custom_new#:#Create Own Provider Settings###07 02 2020 new variable
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Consumers created in Administration do not allow content selection
lti#:#lti_delete_consume_provider#:#Delete Provider###07 02 2020 new variable
lti#:#lti_delete_consume_providers#:#Delete Providers###07 02 2020 new variable
lti#:#lti_delete_provider#:#Delete Provider###07 02 2020 new variable
@@ -11478,6 +11477,7 @@ lti#:#lti_edit_consumer#:#Edit LTI Consumer###31 08 2017 new variable
lti#:#lti_exit#:#Close LTI Session###31 08 2017 new variable
lti#:#lti_exited#:#LTI Session closed###31 08 2017 new variable
lti#:#lti_exited_info#:#LTI Session successfully closed###31 08 2017 new variable
+lti#:#lti_form_provider_content_selection#:#Chọn nội dung
lti#:#lti_form_provider_create#:#Create Provider Settings###07 02 2020 new variable
lti#:#lti_form_provider_edit#:#Edit Provider Settings###07 02 2020 new variable
lti#:#lti_form_section_appearance#:#Options for launch###07 02 2020 new variable
@@ -11529,6 +11529,7 @@ lti#:#subtab_certificate#:#Certificate###07 02 2020 new variable
lti#:#subtab_object_settings#:#Object Settings###07 02 2020 new variable
lti#:#subtab_provider_settings#:#LTI Provider Settings###07 02 2020 new variable
lti#:#tab_content#:#Content###07 02 2020 new variable
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info###07 02 2020 new variable
lti#:#tab_scoring#:#Ranking###07 02 2020 new variable
lti#:#tab_settings#:#Settings###07 02 2020 new variable
diff --git a/lang/ilias_zh.lang b/lang/ilias_zh.lang
index fae47a27d5e3..3b78876234b8 100644
--- a/lang/ilias_zh.lang
+++ b/lang/ilias_zh.lang
@@ -11257,16 +11257,14 @@ lti#:#activity_id#:#Activity ID###07 02 2020 new variable
lti#:#activity_id_info#:#This Activity ID is used by the LTI Provider to identify Statements.###07 02 2020 new variable
lti#:#auth_lti#:#LTI Auth###31 08 2017 new variable
lti#:#conf_privacy_ident#:#User identification###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
-lti#:#conf_privacy_ident_il_uuid_SHA256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###26 08 2024 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
+lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account#:#External User ID combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_ext_account_info#:#This is identical to each call, but may allow a direct conclusion about the user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login#:#ILIAS Login combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_login_info#:#Sends the login name. This is identical to each call, but may allow a direct conclusion about the ILIAS user.###26 08 2024 new variable
lti#:#conf_privacy_ident_il_uuid_random#:#Random ID combined with a unique ILIAS platform ID formatted as an E-Mail address###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_random_info#:#For each ILIAS object and ILIAS user a random ID is generated which remains identical for each call. Conclusions about a user are very limited because it is practically impossible to create user profiles across objects.###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256#:#Hash combined with a unique ILIAS platform id formatted as an E-Mail address###04 12 2025 new variable
-lti#:#conf_privacy_ident_il_uuid_sha256_info#:#This is identical to each call, but does not permit any direct conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url#:#Hash combined with the ILIAS Domain formatted as an E-Mail address.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_sha256url_info#:#This is identical to each call, with with a maximum of 80 characters significantly shorter than the variant with the ILIAS platform ID and allows only very limited conclusions about the ILIAS user.###04 12 2025 new variable
lti#:#conf_privacy_ident_il_uuid_user_id#:#ILIAS user id combined with a unique ILIAS platform id formatted as an E-Mail address###26 08 2024 new variable
@@ -11377,7 +11375,7 @@ lti#:#lti_at_least_one_prov_has_usages#:#At least one provider could not be dele
lti#:#lti_auth_failed_invalid_key#:#Authentication failed, no valid consumer key given.###31 08 2017 new variable
lti#:#lti_con_content_item#:#Support for Deep Linking###26 08 2024 new variable
lti#:#lti_con_content_item_url#:#Content URL###26 08 2024 new variable
-lti#:#lti_con_grade_synchronization#:#Advanced Grading Services###04 12 2025 new variable
+lti#:#lti_con_grade_synchronization#:#Assignment and Grade Services###04 12 2025 new variable
lti#:#lti_con_grade_synchronization_info#:#The LTI tool must offer 'Assignment and Grade Services'.###04 12 2025 new variable
lti#:#lti_con_initiate_login_url#:#Initiate Login URL###26 08 2024 new variable
lti#:#lti_con_key_type#:#Public Key Type###26 08 2024 new variable
@@ -11467,6 +11465,7 @@ lti#:#lti_create_lti_user_role#:#Create recommended global role for LTI users###
lti#:#lti_cron_title#:#LTI Outcome Service###07 02 2020 new variable
lti#:#lti_cron_title_desc#:#Synchronizes the learning progress of LTI users with the LTI consumer, if it supports the outcome service. This cron job is only required to transfer status updates after Learning progress settings updates.###07 02 2020 new variable
lti#:#lti_custom_new#:#Create Own Provider Settings###07 02 2020 new variable
+lti#:#lti_deep_linking_not_available_for_admin_objects#:#Consumers created in Administration do not allow content selection
lti#:#lti_delete_consume_provider#:#Delete Provider###07 02 2020 new variable
lti#:#lti_delete_consume_providers#:#Delete Providers###07 02 2020 new variable
lti#:#lti_delete_provider#:#Delete Provider###07 02 2020 new variable
@@ -11475,6 +11474,7 @@ lti#:#lti_edit_consumer#:#Edit LTI Consumer###31 08 2017 new variable
lti#:#lti_exit#:#Close LTI Session###31 08 2017 new variable
lti#:#lti_exited#:#LTI Session closed###31 08 2017 new variable
lti#:#lti_exited_info#:#LTI Session successfully closed###31 08 2017 new variable
+lti#:#lti_form_provider_content_selection#:#内容选择
lti#:#lti_form_provider_create#:#Create Provider Settings###07 02 2020 new variable
lti#:#lti_form_provider_edit#:#Edit Provider Settings###07 02 2020 new variable
lti#:#lti_form_section_appearance#:#Options for launch###07 02 2020 new variable
@@ -11526,6 +11526,7 @@ lti#:#subtab_certificate#:#Certificate###07 02 2020 new variable
lti#:#subtab_object_settings#:#Object Settings###07 02 2020 new variable
lti#:#subtab_provider_settings#:#LTI Provider Settings###07 02 2020 new variable
lti#:#tab_content#:#Content###07 02 2020 new variable
+lti#:#tab_grade_synchronization#:#Gradebook
lti#:#tab_info#:#Info###07 02 2020 new variable
lti#:#tab_scoring#:#Ranking###07 02 2020 new variable
lti#:#tab_settings#:#Settings###07 02 2020 new variable