Problem

  • The global $lanuage is inconsistent with other language types, misleading for developers and blocks the variable name preventing reuse.

Goal

  • Rename the global $language to be in line with other language types, inform developers better and free up the $language variable name to be used elsewhere.

Details

  • Language types in Drupal core include interface, content and URL. Content and URL have names $language_content and $language_url, while the interface language is simply $language. This makes the naming inconsistent.
  • By naming the interface language $language, developers are fooled into thinking they do language support if they consider this value only. Content and URL language should be used as well when appropriate. Standardizing on names makes it clearer what's to be used in certain cases.
  • The global $language blocks reuse of this variable name. Same as with $base_path, $user, etc. These should not be used in local scopes in other meanings. $user has an $account naming counterpart that is being used, but $language does not have a similar pair. By making global language naming consistent, we free up $language to be used for local values.
  • A lot more discussion happened in #1216094: We call too many things 'language', clean that up where we decided this is the way to go.
  • Even though we do expect the global variables to be integrated into context data later, we do need this renamed *now* to be able to proceed with basic low level API improvements like #1215716: Introduce locale_language_save().

Proposed resolution

  • Rename global $language to $language_interface for consistency, improving developer understanding and awareness and simplifying code elsewhere.
CommentFileSizeAuthor
#74 language-1222194-74.patch1.46 KBplach
#73 1222194-update_fix.patch1.25 KBandypost
#72 1222194-update_fix.patch2.71 KBandypost
#68 1222194-update_fix.patch1.14 KBandypost
#67 locale_blocks.png5.36 KBandypost
#63 language-1222194-63.patch75.07 KBgábor hojtsy
#61 language-1222194-61.patch75.05 KBgábor hojtsy
#54 language-1222194-54.patch74.29 KBplach
#54 language-1222194-54-test.patch72.35 KBplach
#54 language-1222194-54-interdiff.D0.patch1.57 KBplach
#47 language-1222194-47.patch72.72 KBplach
#47 language-1222194-47-test.patch70.78 KBplach
#45 language-1222194-45.patch72.62 KBgábor hojtsy
#43 language-1222194-43.patch71.9 KBplach
#41 language-1222194-38.patch70.46 KBgábor hojtsy
#39 language-1222194-38.patch70.46 KBplach
#37 language-1222194-37.patch70.1 KBplach
#28 language-1222194-28.patch69.66 KBplach
#27 language-1222194-27.patch69.7 KBgábor hojtsy
#24 language-1222194-24.patch69.26 KBplach
#22 global-language-to-language-interface-7.patch68.63 KBgábor hojtsy
#17 global-language-to-language-interface-7.patch68.63 KBgábor hojtsy
#15 global-language-to-language-interface-5.patch68.49 KBgábor hojtsy
#15 global-language-to-language-interface-6.patch67.23 KBgábor hojtsy
#12 global-language-to-language-interface-4.patch67.23 KBgábor hojtsy
#10 global-language-to-language-interface-4.patch64.93 KBgábor hojtsy
#8 global-language-to-language-interface-3.patch57.53 KBgábor hojtsy
#5 global-language-to-language-interface-2.patch45.77 KBgábor hojtsy
#2 global-language-to-language-interface.patch41.19 KBgábor hojtsy
global-language-to-language-ui.patch40.41 KBgábor hojtsy

Comments

sun’s picture

mmm, "ui" is yet another abbreviation. :-/

#1216094: We call too many things 'language', clean that up could have used some more discussion, agreement, and buy-in, before attempting to create a patch, IMHO. But anyway...

I currently see:

/**
 * The type of language used to define the content language.
 */
define('LANGUAGE_TYPE_CONTENT', 'language_content');

/**
 * The type of language used to select the user interface.
 */
define('LANGUAGE_TYPE_INTERFACE', 'language');

/**
 * The type of language used for URLs.
 */
define('LANGUAGE_TYPE_URL', 'language_url');

So the most logical thing would be to have:

/**
 * The type of language used to select the user interface.
 */
define('LANGUAGE_TYPE_INTERFACE', 'language_interface');

and thus, $language_interface.

gábor hojtsy’s picture

StatusFileSize
new41.19 KB

Superb. The patch makes it very easy to search and replace for this. Did that. I think this patch is great because it singles out all the $language values which were global (unless I missed some), so whatever we decide to rename it to, we can. If we want it to be $language_locale_code_key_tag we can make that happen :)

gábor hojtsy’s picture

Status: Needs review » Postponed

Based on discussion with @sun in IRC, marking postponed for now to make sure we get to the right terminology in #1216094: We call too many things 'language', clean that up. The patch is still good to serve as a base to identify what to rename, and depending on the changes done in the interim, might be used to search and replace to generate a new patch later.

gábor hojtsy’s picture

Title: Rename global $langauge to $language_ui » Rename global $langauge to $language_interface
gábor hojtsy’s picture

Status: Postponed » Needs review
StatusFileSize
new45.77 KB

Now this one includes all instances of GLOBALS['language'] as well. That should help with lots of notices, hope it also helps with making tests pass.

plach’s picture

Title: Rename global $langauge to $language_interface » Rename global $language to $language_interface

Coming back later

Status: Needs review » Needs work

The last submitted patch, global-language-to-language-interface-2.patch, failed testing.

gábor hojtsy’s picture

Status: Needs work » Needs review
StatusFileSize
new57.53 KB

Even more places where I found global $language in other constellations. Getting there.

Status: Needs review » Needs work

The last submitted patch, global-language-to-language-interface-3.patch, failed testing.

gábor hojtsy’s picture

Status: Needs work » Needs review
StatusFileSize
new64.93 KB

Evidently I still missed some places in tests where the detection and selection configuration was handled.

Status: Needs review » Needs work

The last submitted patch, global-language-to-language-interface-4.patch, failed testing.

gábor hojtsy’s picture

Status: Needs work » Needs review
StatusFileSize
new67.23 KB

Finally some leftover pieces of classes and block tests.

gábor hojtsy’s picture

Issue summary: View changes

Updated.

gábor hojtsy’s picture

Issue summary: View changes

Used summary template for updated summary. Hopefully even clearer.

gábor hojtsy’s picture

Talked about this in IRC with plach. He says we need to update the 'language_types' variable and rename 'language_negotiation_language' to 'language_negotiation_language_interafce'. No other affected settings identified so far. That is still to be done. Reviews of the patch welcome in the meantime.

plach’s picture

Status: Needs review » Needs work

I reviewed the patch and aside from the stupid thing below it looks ready to go. The bot is doing a far better job at testing it than the one I could do myself. We are still missing an update function, however. About this I found another variable that should be updated: locale_language_providers_weight_language should become locale_language_providers_weight_language_interface.

+++ b/modules/locale/locale.module
@@ -637,11 +637,11 @@ function locale($string = NULL, $context = NULL, $langcode = NULL) {
+  // cache after $language_interface has been set to avoid an unnecessary cache rebuild.

Comment is not wrapping at column 80.

gábor hojtsy’s picture

Status: Needs work » Needs review
StatusFileSize
new67.23 KB
new68.49 KB

@plach: thanks! Here is a version of the patch with updates (5) and one without (6). I think we are currently opening separate issues for the updates to get them tested once they'll actually be run, so not sure we should include that here. Anyway, this is the update function I devised, please review!

/**
 * Language type 'language' renamed to 'language_interface'.
 */
function locale_update_7000() {
  // Only change language_types if we had this setting saved.
  $types = variable_get('language_types', NULL);
  if (!empty($types) && isset($types['lanuguage'])) {
    $types['language_interface'] = $types['language'];
    unset($types['language']);
    variable_set('language_types', $types);
  }

  // Rename language_negotiation_language setting if exists.
  $setting = variable_get('language_negotiation_language', NULL);
  if (!is_null($setting)) {
    variable_set('language_negotiation_language_interface', $setting);
    variable_del('language_negotiation_language');
  }

  // Rename locale_language_providers_weight_language setting if exists.
  $weight = variable_get('locale_language_providers_weight_language', NULL);
  if (!is_null($weight)) {
    variable_set('locale_language_providers_weight_language_interface', $weight);
    variable_del('locale_language_providers_weight_language');
  }
}

Also made the change you spotted for the 80 column issue :)

plach’s picture

Status: Needs review » Needs work
+++ b/modules/locale/locale.install
@@ -262,3 +262,30 @@ function locale_schema() {
+    $types['language_interface'] = $types['language'];
+    unset($types['language']);

I'm a bit worried by this: at a first read it seems that the original key order is not preserved. Since the key order determines the order in which languages are initialized, and content language inherits from interface language, this should lead content language to get an empty value. I guess the bot is not failing because we have no test coverage for D7 > D8 upgrade yet.

+++ b/modules/locale/locale.install
@@ -262,3 +262,30 @@ function locale_schema() {
+  if (!is_null($setting)) {

Why is_null and not $setting === NULL which should be faster?

29 days to next Drupal core point release.

gábor hojtsy’s picture

Status: Needs work » Needs review
StatusFileSize
new68.63 KB

Ok, this should keep the order. I'm not crazy about === NULL, its ok :) What about this?

/**
 * Language type 'language' renamed to 'language_interface'.
 */
function locale_update_7000() {
  // Only change language_types if we had this setting saved. Keep order
  // of types because that is significant for value dependency.
  $types = variable_get('language_types', NULL);
  if (!empty($types) && isset($types['lanuguage'])) {
    $new_types = array();
    foreach ($types as $key => $type) {
      $new_types[$key == 'language' ? 'language_interface' : $key] = $type;
    }
    variable_set('language_types', $new_types);
  }

  // Rename language_negotiation_language setting if exists.
  $setting = variable_get('language_negotiation_language', NULL);
  if ($setting !== NULL) {
    variable_set('language_negotiation_language_interface', $setting);
    variable_del('language_negotiation_language');
  }

  // Rename locale_language_providers_weight_language setting if exists.
  $weight = variable_get('locale_language_providers_weight_language', NULL);
  if ($weight !== NULL) {
    variable_set('locale_language_providers_weight_language_interface', $weight);
    variable_del('locale_language_providers_weight_language');
  }
}
plach’s picture

Now it looks good :)

I'll test the upgrade path myself as soon as I can.

sun’s picture

Status: Needs review » Needs work

um, did you guys already hear about PHP's latest awesome function http://www.php.net/manual/en/function.isset.php ?

lars toomre’s picture

Never will set language_types to $new_types due to misspelling in

if (!empty($types) && isset($types['lanuguage'])) {

Cheers!

plach’s picture

@sun:

yes, I read something about it, not that good after all ;)

gábor hojtsy’s picture

Status: Needs work » Needs review
StatusFileSize
new68.63 KB

@Lars: ha! Looks like I'm close to unlocking the "language word mistyped in most creative ways" badge soon. Fixed that in the attached patch, good catch.

sun’s picture

Issue tags: +API clean-up
plach’s picture

Status: Needs review » Needs work
StatusFileSize
new69.26 KB

We are almost there but not yet: without the fixes below the update won't work.

+++ b/modules/locale/locale.install
@@ -262,3 +262,33 @@ function locale_schema() {
+function locale_update_7000() {

This should be

locale_update_8000() {

Moreover I realized that also the interface language switcher block delta must be renamed from 'language' to 'language_interface'.

Additionally while running the update, if language negotiation settings are present, notices are thrown all around since the global $language_interface is not initialized yet. These can be fixed by adding the following line to update.php (see also the attached patch):

<?php
$GLOBALS[LANGUAGE_TYPE_INTERFACE] = language_default();
?>

29 days to next Drupal core point release.

gábor hojtsy’s picture

Ok, so the only thing you have not done in your updated patch seems to be the data migration for blocks to the new name. Will look into that then.

plach’s picture

Yes, I only made the minimal fixes needed to make the upgrade run smoothly. This way I can review the final patch :)

gábor hojtsy’s picture

Status: Needs work » Needs review
StatusFileSize
new69.7 KB

Thanks! Updated the patch with code to update data in the block, block_role and block_node_type tables.

plach’s picture

StatusFileSize
new69.66 KB

I tested #27 with the fix below and everything looks good. If we need upgrade path tests this is NW otherwise if they need a separate issue this one is RTBC.

+++ b/modules/locale/locale.install
@@ -262,3 +262,46 @@ function locale_schema() {
+      ->condition('module', 'block')

The 'module' column should be 'locale' :)

22 days to next Drupal core point release.

gábor hojtsy’s picture

Talked to catch, he thinks we'd better add some update testing, although nothing will run our updates to test it... :| #1182290: Add boilerplate upgrade path tests is the main culprit.

gábor hojtsy’s picture

Status: Needs review » Closed (duplicate)

Ok, well, I wanted to have this in much sooner, but with no upgrade path tests, this did not get to fruition. At this point however, there is no point in working on this, since we are moving on to have a context system instead of globals. The update related code needs to be taken over to #1260918: Convert language globals to contexts that handles the migration of the language globals to context and will need to do the same or similar rename of the global language.

gábor hojtsy’s picture

Issue tags: +language-base

Tagging for base language system.

Would this make sense to be reopened given that contexts are still not anywhere in sight?

gábor hojtsy’s picture

Issue tags: +negotiation

Tagging for language negotiation too.

gábor hojtsy’s picture

Status: Closed (duplicate) » Needs work
plach’s picture

Issue tags: +sprint

I guess this needs to be done soonish.

plach’s picture

Status: Needs work » Needs review
Issue tags: -API clean-up, -D8MI, -sprint, -language-base, -negotiation

#28: language-1222194-28.patch queued for re-testing.

Status: Needs review » Needs work
Issue tags: +API clean-up, +D8MI, +sprint, +language-base, +negotiation

The last submitted patch, language-1222194-28.patch, failed testing.

plach’s picture

Status: Needs work » Needs review
StatusFileSize
new70.1 KB

This was ugly to reroll. Hope I didn't miss anything.

Status: Needs review » Needs work

The last submitted patch, language-1222194-37.patch, failed testing.

plach’s picture

StatusFileSize
new70.46 KB
+++ b/core/modules/locale/locale.install
@@ -207,6 +207,49 @@ function locale_schema() {
+function locale_update_8000() {

Wrong update number. This should also go in the proper PHP doc group.

20 days to next Drupal core point release.

plach’s picture

Status: Needs work » Needs review
gábor hojtsy’s picture

StatusFileSize
new70.46 KB

Re-uploading for retest. I think testbot was stuck and found no way to get it restested but to upload again.

Status: Needs review » Needs work

The last submitted patch, language-1222194-38.patch, failed testing.

plach’s picture

Status: Needs work » Needs review
StatusFileSize
new71.9 KB

There were a couple of missing places.

Status: Needs review » Needs work

The last submitted patch, language-1222194-43.patch, failed testing.

gábor hojtsy’s picture

Status: Needs work » Needs review
Issue tags: +Needs tests
StatusFileSize
new72.62 KB

Fixed the three remaining places the tests were failing (AFAIS). Locale_test.module, book.module and one more place in locale.module. Also put the new update function under an incrementally increasing number, but before the existing one. We have no reason to mix up the function order, do we?

Even if this passes I think we need update testing for it which would include some of the values touched in the update and ensure it updates properly.

Status: Needs review » Needs work

The last submitted patch, language-1222194-45.patch, failed testing.

plach’s picture

Status: Needs work » Needs review
StatusFileSize
new70.78 KB
new72.72 KB

(Hopefully) The last fix.

Even if this passes I think we need update testing for it which would include some of the values touched in the update and ensure it updates properly.

I ain't sure about this, I think tests would fail if we messed something up in the update function. Let's try without locale_update_8001.

Status: Needs review » Needs work

The last submitted patch, language-1222194-47-test.patch, failed testing.

plach’s picture

Status: Needs work » Needs review

Nice!

However it seems that block upgrade is not test covered, I think a simple assertion about the presence of the language switcher in the page would be enough, right?

gábor hojtsy’s picture

Yes, I think so. (drupal-7.language.database.php does not currently have it enabled though, so that would need to change too).

plach’s picture

drupal-7.language.database.php does not currently have it enabled though, so that would need to change too

Aw, I saw some activity around it in the latest patches. Is there a resource or something I can read to learn the proper way to create/alter the DB dump?

gábor hojtsy’s picture

@plach: its a php file using the D8 DB API, so you can just alter where it adds the block to do state => '1' instead of status => '0' and place it in a region, really nothing special about it.

plach’s picture

Oh, wonderful :)

plach’s picture

Testing again the upgrade path coverage.

Status: Needs review » Needs work

The last submitted patch, language-1222194-54-test.patch, failed testing.

plach’s picture

Status: Needs work » Needs review

Ok, the results look good now.

gábor hojtsy’s picture

Status: Needs review » Reviewed & tested by the community

Yay, I think this looks good, has good update test coverage and all the benefits outlined in the issue summary still stand. I think this looks good to go.

gábor hojtsy’s picture

Issue tags: -Needs tests

Has tests, so no need to tag needs tests.

dries’s picture

This no longer seems to apply and may need a quick re-roll.

vortex:drupal-head dries$ git apply ../f.patch 
error: patch failed: core/modules/locale/locale.module:745
error: core/modules/locale/locale.module: patch does not apply
error: patch failed: core/modules/locale/locale.test:1101
error: core/modules/locale/locale.test: patch does not apply
error: patch failed: core/modules/path/path.test:251
error: core/modules/path/path.test: patch does not apply
error: patch failed: core/modules/simpletest/tests/upgrade/upgrade.language.test:40
error: core/modules/simpletest/tests/upgrade/upgrade.language.test: patch does not apply
error: patch failed: core/modules/translation/translation.test:179
error: core/modules/translation/translation.test: patch does not apply
dries’s picture

#54: language-1222194-54.patch queued for re-testing.

gábor hojtsy’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new75.05 KB

Yes, unfortunately this is the kind of test which is going to fail to apply more and more as it is lingering :/ Attached a reroll with the apply fails fixed (and the newly extended tests in locale hopefully entirely updated). Looking for testbot feedback.

gábor hojtsy’s picture

Status: Needs review » Reviewed & tested by the community

All right then, applies again (for now :).

gábor hojtsy’s picture

StatusFileSize
new75.07 KB

Patch still applied with offsets. Rerolling just to make sure we have a 100% applicable patch (and a fresh test result). There is absolutely no change so should still be RTBC (unless it fails with the current codebase).

dries’s picture

Status: Reviewed & tested by the community » Fixed

Give this another review and it still looks great. No more lingering around; committed to 8.x. Thanks Gabor.

gábor hojtsy’s picture

Issue tags: -sprint

Change notice added at: http://drupal.org/node/1450578 - removing sprint tag.

tim.plunkett’s picture

Dries, if you use single quotes the commit messages won't get messed up. Or, if you have to use double quotes because of apostrophes, don't use `git commit -m` and let it drop you into an editor.

This
- Patch #1222194 by Gábor Hojtsy, plach: Rename global $language to $language_interface().
Became
- Patch #1222194 by Gábor Hojtsy, plach: rename global to ().

andypost’s picture

StatusFileSize
new5.36 KB

Update function for the d8 site with 3 languages are failed for me

locale module
Update #8001
Failed: PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'bartik-locale-language_interface' for key 'tmd': UPDATE {block} SET delta=:db_update_placeholder_0 WHERE (delta = :db_condition_placeholder_0) AND (module = :db_condition_placeholder_1) ; Array ( [:db_update_placeholder_0] => language_interface [:db_condition_placeholder_0] => language [:db_condition_placeholder_1] => locale ) in locale_update_8001() (line 273 of /var/www/core8/core/modules/locale/locale.install).

Suppose this caused that I've visit site before running update and blocks already been rebuild so I have duplicates
locale_blocks.png

andypost’s picture

Status: Fixed » Needs review
StatusFileSize
new1.14 KB

Suppose better to check is there any blocks and clean-up possible auto-created rows

plach’s picture

Status: Needs review » Needs work
+++ b/core/modules/locale/locale.install
@@ -264,13 +264,20 @@ function locale_update_8001() {
+    if (db_query_range("SELECT 1 FROM {" . $table . "} WHERE delta = :delta AND module = :module", 0, 1,
+      array(':delta' => 'language', ':module' => 'locale'))->fetchField()) {

Please, can we have a separate line for the query to improve readability? Moreover a comment to explain why we are performing this check could be useful too.

+++ b/core/modules/locale/locale.install
@@ -264,13 +264,20 @@ function locale_update_8001() {
+      db_update($table)
+        ->fields(array(
+          'delta' => 'language_interface',
+        ))
+        ->condition('delta', 'language')
+        ->condition('module', 'locale')
+        ->execute();

If I'm not missing something the update should be outside the if statement as it should always be executed.

7 days to next Drupal core point release.

andypost’s picture

If I'm not missing something the update should be outside the if statement as it should always be executed.

I suppose that if there's no locale's blocks so no update needed

plach’s picture

I suppose that if there's no locale's blocks so no update needed

Right, I misread the test. It should really be on a separate line.

andypost’s picture

Status: Needs work » Needs review
StatusFileSize
new2.71 KB

Added comment for db_delete()
db_query() changed to one line as all over core we have

andypost’s picture

StatusFileSize
new1.25 KB

Previous patch was wrong

plach’s picture

StatusFileSize
new1.46 KB

Cleaned up comments and readability, otherwise untouched.

gábor hojtsy’s picture

So how can the new blocks be there if the old ones are not yet removed? If a block rebuild would happen, it should remove the old blocks not available anymore too, no? @andypost your block ids look suspicious since the new blocks are before the old? Hm.

andypost’s picture

Status: Needs review » Reviewed & tested by the community

@Gábor Hojtsy it seems block_rehash still bogus.

Steps to reproduce

- git checkout edabf1fc3add074b9818b6fb125e287f6091ab2c
- install core, drush en locale
- git checkout a58940f111b76df8141eaa9a8096ef087dd2944c
- visit admin/structure/block/list/seven and admin/structure/block
drush sqlc
mysql> select * from block where module='locale';
+-----+--------+--------------------+--------+--------+--------+--------+--------+------------+-------+-------+-------+
| bid | module | delta              | theme  | status | weight | region | custom | visibility | pages | title | cache |
+-----+--------+--------------------+--------+--------+--------+--------+--------+------------+-------+-------+-------+
|  31 | locale | language           | bartik |      0 |      0 | -1     |      0 |          0 |       |       |    -1 |
|  32 | locale | language           | seven  |      0 |      0 | -1     |      0 |          0 |       |       |    -1 |
|  33 | locale | language_interface | bartik |      0 |      0 | -1     |      0 |          0 |       |       |    -1 |
|  34 | locale | language_interface | seven  |      0 |      0 | -1     |      0 |          0 |       |       |    -1 |
+-----+--------+--------------------+--------+--------+--------+--------+--------+------------+-------+-------+-------+
4 rows in set (0.01 sec)
gábor hojtsy’s picture

@andypost: ok, I guess that is because the language provider data is also cached and not yet updated. So I agree the patch looks good to solve the problem.

catch’s picture

Status: Reviewed & tested by the community » Fixed

OK I asked Gabor in IRC why the updated didn't come with tests, but it's apparently only possible to hit this if you hit your site while also upgrading. The change is small enough and the bug obscure enough that I've gone ahead and committed this.

Automatically closed -- issue fixed for 2 weeks with no activity.

Anonymous’s picture

Issue summary: View changes

Mistyped some stuff