Problem/Motivation

We currently use t() in some exceptions, but we don't translate exceptions. In the installer there are some

Examples:

./includes/common.inc:    throw new Exception(t('Archivers can only operate on local files: %file not supported', array('%file' => $file)));
./includes/install.core.inc:        throw new InstallerException(t('Missing profile parameter.'));
./includes/install.core.inc:        throw new InstallerException(t('Sorry, you must select a language to continue the installation.'));
./includes/install.inc:      throw new Exception(t('Failed to modify %settings. Verify the file permissions.', array('%settings' => $settings_file)));
./includes/install.inc:    throw new Exception(t('Failed to open %settings. Verify the file permissions.', array('%settings' => $settings_file)));
./includes/install.inc:      throw new Exception(t('The directory %directory could not be created or could not be made writable. To proceed with the installation, either create the directory and modify its permissions manually or ensure that the installer has the permissions to create it automatically. For more information, see the <a href="@handbook_url">online handbook</a>.', array(
./includes/update.inc: * throw new UpdateException(t('Description of what went wrong'));
./lib/Drupal/Core/Archiver/Zip.php:      throw new ArchiverException(t('Cannot open %file_path', array('%file_path' => $file_path)));
./lib/Drupal/Core/Database/Driver/mysql/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot rename @table to @table_new: table @table doesn't exist.", array('@table' => $table, '@table_new' => $new_name)));
./lib/Drupal/Core/Database/Driver/mysql/Schema.php:      throw new SchemaObjectExistsException(t("Cannot rename @table to @table_new: table @table_new already exists.", array('@table' => $table, '@table_new' => $new_name)));
./lib/Drupal/Core/Database/Driver/mysql/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot add field @table.@field: table doesn't exist.", array('@field' => $field, '@table' => $table)));
./lib/Drupal/Core/Database/Driver/mysql/Schema.php:      throw new SchemaObjectExistsException(t("Cannot add field @table.@field: field already exists.", array('@field' => $field, '@table' => $table)));
./lib/Drupal/Core/Database/Driver/mysql/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot set default value of field @table.@field: field doesn't exist.", array('@table' => $table, '@field' => $field)));
./lib/Drupal/Core/Database/Driver/mysql/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot remove default value of field @table.@field: field doesn't exist.", array('@table' => $table, '@field' => $field)));
./lib/Drupal/Core/Database/Driver/mysql/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot add primary key to table @table: table doesn't exist.", array('@table' => $table)));
./lib/Drupal/Core/Database/Driver/mysql/Schema.php:      throw new SchemaObjectExistsException(t("Cannot add primary key to table @table: primary key already exists.", array('@table' => $table)));
./lib/Drupal/Core/Database/Driver/mysql/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot add unique key @name to table @table: table doesn't exist.", array('@table' => $table, '@name' => $name)));
./lib/Drupal/Core/Database/Driver/mysql/Schema.php:      throw new SchemaObjectExistsException(t("Cannot add unique key @name to table @table: unique key already exists.", array('@table' => $table, '@name' => $name)));
./lib/Drupal/Core/Database/Driver/mysql/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot add index @name to table @table: table doesn't exist.", array('@table' => $table, '@name' => $name)));
./lib/Drupal/Core/Database/Driver/mysql/Schema.php:      throw new SchemaObjectExistsException(t("Cannot add index @name to table @table: index already exists.", array('@table' => $table, '@name' => $name)));
./lib/Drupal/Core/Database/Driver/mysql/Schema.php:      throw new SchemaIndexNotInSpecException(t("The index @name doesn't exist in the @table table specification.", array('@table' => $table, '@name' => $name)));
./lib/Drupal/Core/Database/Driver/mysql/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot add index @name to table @table: table doesn't exist.", array('@table' => $table, '@name' => $name)));
./lib/Drupal/Core/Database/Driver/mysql/Schema.php:      throw new SchemaObjectExistsException(t("Cannot add index @name to table @table: index already exists.", array('@table' => $table, '@name' => $name)));
./lib/Drupal/Core/Database/Driver/mysql/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot change the definition of field @table.@name: field doesn't exist.", array('@table' => $table, '@name' => $field)));
./lib/Drupal/Core/Database/Driver/mysql/Schema.php:      throw new SchemaObjectExistsException(t("Cannot rename field @table.@name to @name_new: target field already exists.", array('@table' => $table, '@name' => $field, '@name_new' => $field_new)));
./lib/Drupal/Core/Database/Driver/pgsql/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot rename @table to @table_new: table @table doesn't exist.", array('@table' => $table, '@table_new' => $new_name)));
./lib/Drupal/Core/Database/Driver/pgsql/Schema.php:      throw new SchemaObjectExistsException(t("Cannot rename @table to @table_new: table @table_new already exists.", array('@table' => $table, '@table_new' => $new_name)));
./lib/Drupal/Core/Database/Driver/pgsql/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot add field @table.@field: table doesn't exist.", array('@field' => $field, '@table' => $table)));
./lib/Drupal/Core/Database/Driver/pgsql/Schema.php:      throw new SchemaObjectExistsException(t("Cannot add field @table.@field: field already exists.", array('@field' => $field, '@table' => $table)));
./lib/Drupal/Core/Database/Driver/pgsql/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot set default value of field @table.@field: field doesn't exist.", array('@table' => $table, '@field' => $field)));
./lib/Drupal/Core/Database/Driver/pgsql/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot remove default value of field @table.@field: field doesn't exist.", array('@table' => $table, '@field' => $field)));
./lib/Drupal/Core/Database/Driver/pgsql/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot add primary key to table @table: table doesn't exist.", array('@table' => $table)));
./lib/Drupal/Core/Database/Driver/pgsql/Schema.php:      throw new SchemaObjectExistsException(t("Cannot add primary key to table @table: primary key already exists.", array('@table' => $table)));
./lib/Drupal/Core/Database/Driver/pgsql/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot add unique key @name to table @table: table doesn't exist.", array('@table' => $table, '@name' => $name)));
./lib/Drupal/Core/Database/Driver/pgsql/Schema.php:      throw new SchemaObjectExistsException(t("Cannot add unique key @name to table @table: unique key already exists.", array('@table' => $table, '@name' => $name)));
./lib/Drupal/Core/Database/Driver/pgsql/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot add index @name to table @table: table doesn't exist.", array('@table' => $table, '@name' => $name)));
./lib/Drupal/Core/Database/Driver/pgsql/Schema.php:      throw new SchemaObjectExistsException(t("Cannot add index @name to table @table: index already exists.", array('@table' => $table, '@name' => $name)));
./lib/Drupal/Core/Database/Driver/pgsql/Schema.php:      throw new SchemaIndexNotInSpecException(t("The index @name doesn't exist in the @table table specification.", array('@table' => $table, '@name' => $name)));
./lib/Drupal/Core/Database/Driver/pgsql/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot add index @name to table @table: table doesn't exist.", array('@table' => $table, '@name' => $name)));
./lib/Drupal/Core/Database/Driver/pgsql/Schema.php:      throw new SchemaObjectExistsException(t("Cannot add index @name to table @table: index already exists.", array('@table' => $table, '@name' => $name)));
./lib/Drupal/Core/Database/Driver/pgsql/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot change the definition of field @table.@name: field doesn't exist.", array('@table' => $table, '@name' => $field)));
./lib/Drupal/Core/Database/Driver/pgsql/Schema.php:      throw new SchemaObjectExistsException(t("Cannot rename field @table.@name to @name_new: target field already exists.", array('@table' => $table, '@name' => $field, '@name_new' => $field_new)));
./lib/Drupal/Core/Database/Driver/sqlite/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot rename @table to @table_new: table @table doesn't exist.", array('@table' => $table, '@table_new' => $new_name)));
./lib/Drupal/Core/Database/Driver/sqlite/Schema.php:      throw new SchemaObjectExistsException(t("Cannot rename @table to @table_new: table @table_new already exists.", array('@table' => $table, '@table_new' => $new_name)));
./lib/Drupal/Core/Database/Driver/sqlite/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot add field @table.@field: table doesn't exist.", array('@field' => $field, '@table' => $table)));
./lib/Drupal/Core/Database/Driver/sqlite/Schema.php:      throw new SchemaObjectExistsException(t("Cannot add field @table.@field: field already exists.", array('@field' => $field, '@table' => $table)));
./lib/Drupal/Core/Database/Driver/sqlite/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot change the definition of field @table.@name: field doesn't exist.", array('@table' => $table, '@name' => $field)));
./lib/Drupal/Core/Database/Driver/sqlite/Schema.php:      throw new SchemaObjectExistsException(t("Cannot rename field @table.@name to @name_new: target field already exists.", array('@table' => $table, '@name' => $field, '@name_new' => $field_new)));
./lib/Drupal/Core/Database/Driver/sqlite/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot add index @name to table @table: table doesn't exist.", array('@table' => $table, '@name' => $name)));
./lib/Drupal/Core/Database/Driver/sqlite/Schema.php:      throw new SchemaObjectExistsException(t("Cannot add index @name to table @table: index already exists.", array('@table' => $table, '@name' => $name)));
./lib/Drupal/Core/Database/Driver/sqlite/Schema.php:     throw new SchemaIndexNotInSpecException(t("The index @name doesn't exist in the @table table specification.", array('@table' => $table, '@name' => $name)));
./lib/Drupal/Core/Database/Driver/sqlite/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot add index @name to table @table: table doesn't exist.", array('@table' => $table, '@name' => $name)));
./lib/Drupal/Core/Database/Driver/sqlite/Schema.php:      throw new SchemaObjectExistsException(t("Cannot add index @name to table @table: index already exists.", array('@table' => $table, '@name' => $name)));
./lib/Drupal/Core/Database/Driver/sqlite/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot add unique key @name to table @table: table doesn't exist.", array('@table' => $table, '@name' => $name)));
./lib/Drupal/Core/Database/Driver/sqlite/Schema.php:      throw new SchemaObjectExistsException(t("Cannot add unique key @name to table @table: unique key already exists.", array('@table' => $table, '@name' => $name)));
./lib/Drupal/Core/Database/Driver/sqlite/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot add primary key to table @table: table doesn't exist.", array('@table' => $table)));
./lib/Drupal/Core/Database/Driver/sqlite/Schema.php:      throw new SchemaObjectExistsException(t("Cannot add primary key to table @table: primary key already exists.", array('@table' => $table)));
./lib/Drupal/Core/Database/Driver/sqlite/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot set default value of field @table.@field: field doesn't exist.", array('@table' => $table, '@field' => $field)));
./lib/Drupal/Core/Database/Driver/sqlite/Schema.php:      throw new SchemaObjectDoesNotExistException(t("Cannot remove default value of field @table.@field: field doesn't exist.", array('@table' => $table, '@field' => $field)));
./lib/Drupal/Core/Database/Install/Tasks.php:          throw new TaskException(t("Failed to run all tasks against the database server. The task %task wasn't found.", array('%task' => $task['function'])));
./lib/Drupal/Core/Database/Query/Merge.php:        throw new InvalidMergeQueryException(t('Invalid merge query: no conditions'));
./lib/Drupal/Core/Database/Schema.php:      throw new SchemaObjectExistsException(t('Table @name already exists.', array('@name' => $name)));
./lib/Drupal/Core/Template/TwigExtension.php:        throw new \Exception(t('Object of type "@class" cannot be printed.', array('@class' => get_class($arg))));
./lib/Drupal/Core/Template/TwigExtension.php:        throw new \Exception(t('Object of type "@class" cannot be printed.', array('@class' => get_class($arg))));
./lib/Drupal/Core/Theme/ThemeManager.php:      throw new \Exception(t('_theme() may not be called until all modules are loaded.'));
./lib/Drupal/Core/Updater/Updater.php:      throw new UpdaterException(t('Unable to determine the type of the source directory.'));
./lib/Drupal/Core/Updater/Updater.php:    throw new UpdaterException(t('Cannot determine the type of project.'));
./lib/Drupal/Core/Updater/Updater.php:      throw new UpdaterException(t('Unable to parse info file: %info_file.', ['%info_file' => $info_file]));
./lib/Drupal/Core/Updater/Updater.php:      throw new UpdaterException(t('Unable to parse info file: %info_file.', array('%info_file' => $info_file)));
./lib/Drupal/Core/Updater/Updater.php:        throw new UpdaterException(t('Fatal error in update, cowardly refusing to wipe out the install directory.'));
./lib/Drupal/Core/Updater/Updater.php:      throw new UpdaterFileTransferException(t('File Transfer failed, reason: !reason', array('!reason' => strtr($e->getMessage(), $e->arguments))));
./lib/Drupal/Core/Updater/Updater.php:      throw new UpdaterFileTransferException(t('File Transfer failed, reason: !reason', array('!reason' => strtr($e->getMessage(), $e->arguments))));
./modules/contextual/src/ContextualController.php:      throw new BadRequestHttpException(t('No contextual ids specified.'));
./modules/dblog/src/Plugin/rest/resource/DBLogResource.php:      throw new NotFoundHttpException(t('Log entry with ID @id was not found', array('@id' => $id)));
./modules/dblog/src/Plugin/rest/resource/DBLogResource.php:    throw new HttpException(t('No log entry ID was provided'));
./modules/field/field.api.php:      throw new \Drupal\Core\Entity\Exception\FieldStorageDefinitionUpdateForbiddenException(t('A list field (@field_name) with existing data cannot have its keys changed.', array('@field_name' => $field_storage->getName())));
./modules/field/field.purge.inc:    throw new FieldException(t('Attempt to purge a field storage @field_name that still has fields.', array('@field_name' => $field_storage->getName())));
./modules/node/node.module:      throw new Exception(t('Query tagged for node access but there is no node table, specify the base_table using meta data.'));
./modules/options/options.module:      throw new FieldStorageDefinitionUpdateForbiddenException(t('A list field (@field_name) with existing data cannot have its keys changed.', array('@field_name' => $field_storage->getName())));
./modules/rdf/rdf.module:        throw new Exception(t('Tried to map @prefix to @namespace, but @prefix is already mapped to @orig_namespace.', array('@prefix' => $prefix, '@namespace' => $namespace, '@orig_namespace' => $namespaces[$prefix])));
./modules/system/tests/modules/common_test/common_test.module:  throw new Exception(t('Uncaught exception'));
./modules/update/update.manager.inc:    throw new Exception(t('Cannot extract %file, not a valid archive.', array ('%file' => $file)));

Proposed resolution

Don't use t() in exceptions.

Also, per @dawehner:

There is a limited subset of exceptions which get t() in order to translate error message in the installer. Ideally we would have classed exceptions for all of them, so we could translate them at a more outer level.

Remaining tasks

Review patch

User interface changes

N/A

API changes

N/A

Data model changes

N/A

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

tim.plunkett’s picture

Title: Use SafeMarkup::format instead of t() in exceptions » Do not use t() in exceptions
pguillard’s picture

Assigned: Unassigned » pguillard

I take it

dawehner’s picture

@pguillard
There is a limited subset of exceptions which get t() in order to translate error message in the installer. Ideally we would have classed exceptions for all of them, so we could translate them at a more outer level.

pguillard’s picture

Ooops Thank you @dawehner.
Just in case it can be usefull, I uploaded the patch, I had not finished yet, but stopped there.

afi13’s picture

I want to help with this issue. How can i do it?

afi13’s picture

Assigned: Unassigned » afi13
dawehner’s picture

Status: Active » Needs review

It is always great to see early failures.

Status: Needs review » Needs work

The last submitted patch, 4: do_not_use_t_in_exceptions-2538814-3.patch, failed testing.

afi13’s picture

longwave’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, 9: do_not_use_t_in_exceptions-2538814-9.patch, failed testing.

stefan.r’s picture

Status: Needs work » Needs review
FileSize
6.27 KB
41.64 KB

reroll

stefan.r’s picture

Issue summary: View changes
afi13’s picture

Assigned: afi13 » Unassigned
dawehner’s picture

  1. +++ b/core/includes/install.inc
    @@ -316,7 +317,7 @@ function drupal_rewrite_settings($settings = array(), $settings_file = NULL) {
    -      throw new Exception(t('Failed to modify %settings. Verify the file permissions.', array('%settings' => $settings_file)));
    +      throw new Exception(sprintf('Failed to modify %s. Verify the file permissions.', SafeMarkup::checkPlain($settings_file)));
    
    @@ -333,7 +334,7 @@ function drupal_rewrite_settings($settings = array(), $settings_file = NULL) {
    -    throw new Exception(t('Failed to open %settings. Verify the file permissions.', array('%settings' => $settings_file)));
    +    throw new Exception(sprintf('Failed to open %s. Verify the file permissions.', SafeMarkup::checkPlain($settings_file)));
    

    So these needs discussion, do we want to be able to translate those basic error messages during the installer? You could implement that by having custom exception classes for those different errors and listen to the

  2. +++ b/core/lib/Drupal/Core/Theme/ThemeManager.php
    @@ -141,7 +141,7 @@ public function render($hook, array $variables) {
         if (!$this->moduleHandler->isLoaded() && !defined('MAINTENANCE_MODE')) {
    -      throw new \Exception(t('_theme() may not be called until all modules are loaded.'));
    +      throw new \Exception('_theme() may not be called until all modules are loaded.');
         }
    

    Do you mind opening a follow for that? This should be an assertion IMHO?

  3. +++ b/core/lib/Drupal/Core/Theme/ThemeManager.php
    diff --git a/core/lib/Drupal/Core/Updater/Updater.php b/core/lib/Drupal/Core/Updater/Updater.php
    index 4f56cd9..c5c2ce1 100644
    
    index 4f56cd9..c5c2ce1 100644
    --- a/core/lib/Drupal/Core/Updater/Updater.php
    
    --- a/core/lib/Drupal/Core/Updater/Updater.php
    +++ b/core/lib/Drupal/Core/Updater/Updater.php
    
    +++ b/core/lib/Drupal/Core/Updater/Updater.php
    +++ b/core/lib/Drupal/Core/Updater/Updater.php
    @@ -7,6 +7,7 @@
    

    Some of them seems to be user oriented, aren't they?

afi13’s picture

And that

throw new InstallerException(t('Sorry, you must select a language to continue the installation.'));

So, we can use InstallerException class for all install exception and translate it messages?

afi13’s picture

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

andypost’s picture

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

xjm’s picture

Status: Needs review » Closed (duplicate)
Related issues: +#2055851: Remove translation of exception messages