Comments

gábor hojtsy’s picture

Also, #1301148: Stop pretending we have configuration translation for languages either needs to be implemented in this issue or I need to postpone this one on that too. Once that and the above land, we'll have a pristine language list managed with no fuss hopefully :) That can be separated without pain from the rest of locale.

gábor hojtsy’s picture

Status: Postponed » Needs review
StatusFileSize
new39.92 KB

Here is a very initial take on this patch, which will show how big of a task this is.

1. We need to use this opportunity to rename the table to take ownership of the new schema. The old languages table will need to be dropped.
2. Therefore all uses of the languages table needed updates.
3. I've just moved the language schema and the save and delete API functions and still this patch became pretty darn big due to the above baggage. Broke out the locale / ui translation related code to hook implementations to react to the language changes.

Did not move any of the admin UI for this and no update function yet since we are trying to get these patches land for that before that can happen:

#1260860: Rework language list admin user interface
#1296566: Improve usability of add language screen
#1301148: Stop pretending we have configuration translation for languages
#1301460: Decouple domain/path language negotiation storage from language config storage

Although I took care to update most stuff, this might or might not fail in a huge fire when the tests run :)

Status: Needs review » Needs work

The last submitted patch, language-module-take-0.patch, failed testing.

gábor hojtsy’s picture

Status: Needs work » Needs review
StatusFileSize
new40.35 KB

Surprisingly it mostly fails on the native name thing, which is not yet removed, so should be in the schema still. Added back there.

Status: Needs review » Needs work

The last submitted patch, language-module-take-0.patch, failed testing.

gábor hojtsy’s picture

Status: Needs work » Needs review
StatusFileSize
new40.76 KB

Update for remaining test fail to make locale uninstall test pass for now. We cannot solve all things in one patch.

gábor hojtsy’s picture

StatusFileSize
new38.54 KB

Rerolled for #1260510: Introduce a language_load($langcode) and other patches being landed. Because the painful interconnection with negotiation and localization, I still consider this dependent on #1301148: Stop pretending we have configuration translation for languages and #1301460: Decouple domain/path language negotiation storage from language config storage but the attached patch should be a sneak peak at what is coming. (Once we have those two patches landing, we can move the admin pages as well and update the schema here and put in an update function :).

gábor hojtsy’s picture

gábor hojtsy’s picture

Priority: Normal » Major
gábor hojtsy’s picture

StatusFileSize
new70.82 KB

Ok, here is a quick reroll since all dependencies are now committed. To reiterate, the major goal of this patch is to separate the language management functionality itself from the negotiation/localization/date format, etc. heap of code. Whether we want to move negotiation with this as well I think we can even discuss later, this is already a huge patch which has LOTS of advantages.

- renames 'languages' table to 'language' as per current Drupal code style (@todo lacks update code)
- renames locale_language_save/delete to language_save/delete (language_load() was already lacking the locale_ prefix)
- renames related hooks alike
- moves language admin forms from locale.admin.inc to language.admin.inc and renames them for consistency (locale_language_* and locale_languages_* to language_admin_*)
- untangles interface and language related code, like moving interface translation cache rebuilds in language_save and language_delete to hook implementations, move the language add screen batch sets to interface translation from language management

I think this in itself is a huge improvement. What I believe is @todo for this issue:

- move tests to language.test that are relevant for language list management only
- make sure tests properly pass (they might or might not at this point)
- add an update function for the table rename

What should be done in follow up patches:

- rename the language.language column to language.langcode
- do multiple passes on the code moved to clean up messages, etc. I did lots of fixes for %code => %langcode, %locale => %language, etc, but there might be more
- discuss whether to move language negotiation to this module or to a new module as previously discussed in #1293304: Break up locale.module, but how?
- work on the user and node language selectors which are now in locale module, but should not be, this is being worked on in #540294: Move node language settings from Locale to Node module, #1280996: New language_select element type for form API et. al.

This is a huge patch in itself (and I think a huge improvement), so I think we should keep it focused, therefore the plans for followups.

gábor hojtsy’s picture

StatusFileSize
new70.81 KB

Fixed a few more languages table names missed.

Status: Needs review » Needs work

The last submitted patch, language-module-11.patch, failed testing.

gábor hojtsy’s picture

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

Minor issues caused test failures, now fixed. There should still be a test failure due to the missing upgrade path (yay for having test coverage for that now).

Status: Needs review » Needs work

The last submitted patch, language-module-13.patch, failed testing.

plach’s picture

The plan sounds good to me. Hope to review this soon...

gábor hojtsy’s picture

StatusFileSize
new76.44 KB
new5.33 KB

Here are some fixes to tests (to update them to latest standardized message text used in module). Also, added one-line table rename update path, which is needed to be able to do bootstrap. I doubt this will now work well with the locale update functions, since those then assume a table named 'languages' vs. a table named language. We maybe need to move the whole thing to the update.inc code instead of update functions I guess. Added interdiff from last patch too.

gábor hojtsy’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, language-module-16.patch, failed testing.

gábor hojtsy’s picture

Status: Needs work » Needs review
StatusFileSize
new76.44 KB

Wup, inline edits broke PHP.

Status: Needs review » Needs work

The last submitted patch, language-module-19.patch, failed testing.

gábor hojtsy’s picture

Status: Needs work » Needs review
StatusFileSize
new76.44 KB

One more syntax error :)

Status: Needs review » Needs work

The last submitted patch, language-module-21.patch, failed testing.

gábor hojtsy’s picture

Status: Needs work » Needs review
StatusFileSize
new76.44 KB

Dressing this up with a db_table_exists(). We cannot assume a languages table would exist on all databases obviously.

Status: Needs review » Needs work

The last submitted patch, language-module-23.patch, failed testing.

gábor hojtsy’s picture

Status: Needs work » Needs review
StatusFileSize
new76.49 KB

Wups, that patch had no change there... So now adding the db_table_exists() for real.

Status: Needs review » Needs work

The last submitted patch, language-module-25.patch, failed testing.

gábor hojtsy’s picture

Status: Needs work » Needs review
StatusFileSize
new80.41 KB

Moved all update functions to update.inc that affect the language table / negotiation in bootstrap, to make D8 bootstrap ready with the new language list. What we do with the existing update functions is question of #1333898: Support unstable2unstable upgrades? [policy, no patch] (I'm not clear what was/is the decision there). I removed the updates instead of making them no-ops for now. I'll cross-link this issue with that.

Status: Needs review » Needs work

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

gábor hojtsy’s picture

Seems like the only remaining fail is about the path prefix not getting properly assigned to non-default English, which I locally tracked down to English not being in the path prefix array even with an empty string. That seems to be due to the fact that now the language list is managed before locale is enabled, so locale cannot just assume that all languages are in the prefix/domain arrays. When locale is enabled, it should prefill those values for all the languages configured. I don't have time to fix that right now, anybody coming around sooner, feel free to grab and do so :)

gábor hojtsy’s picture

Status: Needs work » Needs review
StatusFileSize
new81.42 KB

Patch updated with a locale_enable() that does the prefix/domain data matching as needed when locale is enabled (either the first time or any other time later). It removes prefixes and domains that are for removed languages and adds ones for languages added in the meantime. In case locale is enabled and disabled independently from language module, which is clearly what we want to support.

gábor hojtsy’s picture

Submitted #1357918: Missing update for language_default in language langcode update as a followup for this issue to clean up the schema, and hopefully get it to its final D8 form at last for the language list :) Yay. The other followup suggestions seem to be covered with issues already.

So with the update code done and the passing tests (including update tests), we should talk about any review feedback for the patch + whether we want to move tests around here. I think its a huge-huge patch, so maybe we want to do that in a followup too, but comments are absolutely welcome.

plach’s picture

we should talk about any review feedback for the patch + whether we want to move tests around here

Do you mean having tests in a separate patch?

gábor hojtsy’s picture

Yeah, we don't add any new functionality here, we merely separate what we have to establish a more logical organization for the code. The existing tests should cover what we have. We do need to review if we have any tests that are solely testing the language functionality, and move those here and/or add specific tests for just that and remove some (at that point extraneus) coverage from locale module I think. because we are already above 80k, this looks like doable in a separate patch, since we don't need to add any new tests, its just about reorganizing the tests too.

plach’s picture

Agreed, waiting for update code and bot green to review this :)

gábor hojtsy’s picture

The update code is in there, the bot would not be green without it now that we have locale in the update schema :) Looking forward for your review! :)

plach’s picture

Nice, it seems I misunderstood #31 after all ;)

fastangel’s picture

Hi,

I applied the patch #31 and revising. Hen I created content different languages, locale settings, .... In short everything that makes the patch. And it has worked properly.

sun’s picture

Status: Needs review » Needs work

Very nice to see this patch coming along!

+++ b/core/modules/language/language.api.php
@@ -0,0 +1,62 @@
+ /**
+ * React to a language about to be added or updated in the system.
...
+function hook_language_presave($language) {

phpDoc indentation error (first line).

+++ b/core/modules/language/language.info
@@ -0,0 +1,6 @@
+name = Language

We don't have any (pure) language tests?

+++ b/core/modules/language/language.install
@@ -0,0 +1,75 @@
+  variable_del('language_count');

Nice novice follow-up issue: This should really really be a simple cache entry instead of a variable.

+++ b/core/modules/language/language.install
@@ -0,0 +1,75 @@
+  // Re-initialize the language system so successive calls to t() and other
+  // functions will not expect languages to be present.
+  drupal_language_initialize();

+++ b/core/modules/language/language.module
@@ -0,0 +1,189 @@
+  // Kill the static cache in language_list().
+  drupal_static_reset('language_list');

Interesting: language_save() and language_uninstall() both seem to intend to do the same, but are using very different approaches to achieve it. The approach in language_uninstall() looks nicer to me.

That said, btw, this is a very clear case where WSCCI's decision to lock contexts will totally blow up -- it only allows to create a new context layer to be passed forward, but in destructive operations, the global (or parent) context(s) actually need to be replaced/adjusted.

+++ b/core/modules/language/language.module
@@ -0,0 +1,189 @@
+ * @file
+ *   Add language handling functionality to Drupal.

There should not be an indentation for @file summary.

+++ b/core/modules/language/language.module
@@ -0,0 +1,189 @@
+  $items['admin/config/regional/language/overview'] = array(
+    'title' => 'List',

Can we rename the path to end with 'list', too? It's the default local task, so changing the path suffix shouldn't have any impact.

+++ b/core/modules/language/language.module
@@ -0,0 +1,189 @@
+  $items['admin/config/regional/language/edit/%language'] = array(
...
+  $items['admin/config/regional/language/delete/%language'] = array(

Likewise, nice novice follow-up issue: Use entity-alike paths here; i.e., .../language/%language/edit, and /delete.

+++ b/core/modules/language/language.module
@@ -0,0 +1,189 @@
+function language_save($language) {
...
+    drupal_write_record('language', $language);

In a (novice) follow-up issue, we should replace drupal_write_record() with db_merge() in language_save().

+++ b/core/modules/locale/locale.bulk.inc
@@ -18,14 +18,15 @@ function locale_translate_import_form($form) {
+  include_once drupal_get_path('module', 'language') . '/language.admin.inc';

Form constructors have to use form_load_include() to include any file they use to construct the form.

+++ b/core/modules/locale/locale.install
@@ -6,12 +6,30 @@
+ * Language module might change the list of languages, so we need to filter
+ * out the languages from the prefix and domain settings that are not anymore
+ * relevant and add new items that are now needed. This should run every time
+ * the module is enabled.
...
+function locale_enable() {

I'm missing a bit that explains why this needs to happen and why it's important (or not).

I'm also not sure whether it's a good idea to automatically update configuration. Don't we usually throw an error via hook_requirements() instead and point out the problem to the site administrator, so he/she can take the appropriate actions to resolve the inconsistency/problems?

In other words, what if a language was mistakenly removed? While I appreciate the idea of automatically cleaning up the system where possible, this code here actually goes ahead and destroys and /dev/nulls configuration that might have taken some time to figure out and setup.

+++ b/core/modules/locale/locale.module
@@ -620,12 +554,18 @@ function locale_locale_language_insert($language) {
+  cache_clear_all('*', 'cache_page', TRUE);

@@ -639,12 +579,17 @@ function locale_locale_language_update($language) {
+  cache_clear_all('*', 'cache_page', TRUE);

@@ -654,6 +599,19 @@ function locale_locale_language_delete($language) {
+  cache('page')->flush();

The latter one is preferred, I think.

23 days to next Drupal core point release.

plach’s picture

Altough I'm still concerned with the UX implications of splitting Locale in many modules, I'm mostly happy with this patch: from an architectural perspective it looks great. I ain't sure about the Locale upgrade path refactoring, since there is #1333898: Support unstable2unstable upgrades? [policy, no patch] being revisited, but aside from that only minor remarks:

+++ b/core/includes/update.inc
+++ b/core/includes/update.inc
@@ -100,6 +100,42 @@ function update_prepare_d8_bootstrap() {

What about isolating the following changes into a separate function such as update_prepare_d8_language() to improve the readbility of update_prepare_d8_bootstrap()?

+++ b/core/includes/update.inc
@@ -100,6 +100,42 @@ function update_prepare_d8_bootstrap() {
+        // Finally rename the languages table to language.
+        db_rename_table('languages', 'language');

Atfer renaming the table we need to enable the Language module, otherwise the requirements check won't pass (Locale is enabled but Language not).

+++ b/core/modules/language/language.admin.inc
@@ -0,0 +1,438 @@
+    return confirm_form($form, t('Are you sure you want to delete the language %language?', array('%language' => $languages[$langcode]->name)), 'admin/config/regional/language', t('Deleting a language will remove all interface translations associated with it, and posts in this language will be set to be language neutral. This action cannot be undone.'), t('Delete'), t('Cancel'));

Why using %language and not keeping %name?

+++ b/core/modules/language/language.admin.inc
@@ -0,0 +1,438 @@
+    $t_args = array('%language' => $language->name, '%langcode' => $language->language);

See above.

+++ b/core/modules/language/language.admin.inc
@@ -0,0 +1,438 @@
+/**
+ * Prepare language code list for unused predefined languages.

Should not this be "Prepare the language code list ..."?

+++ b/core/modules/locale/locale.install
@@ -6,12 +6,30 @@
+

Is this empty newline intended?

+++ b/core/modules/locale/locale.install
@@ -6,12 +6,30 @@
+  $languages = language_list();
+  $prefixes_old = locale_language_negotiation_url_prefixes();
+  $domains_old = locale_language_negotiation_url_domains();

We need to require_once DRUPAL_ROOT .'/core/includes/locale.inc'; here.

+++ b/core/modules/locale/locale.module
@@ -1179,23 +1092,50 @@ function locale_form_locale_language_overview_form_alter(&$form, &$form_state) {
+  // See if we have language files to import for the newly added
+  // language, collect and import them.
+  include_once drupal_get_path('module', 'locale') . '/locale.bulk.inc';
+  if ($batch = locale_translate_batch_import_files($langcode, TRUE)) {
+    batch_set($batch);
+  }

What about keeping a separate locale_languages_add_set_batch() function for these lines?

24 days to next Drupal core point release.

gábor hojtsy’s picture

Assigned: Unassigned » gábor hojtsy

@sun:

- DONE: solved phpdoc

- FOLLOWUP: we don't have pure language tests, discussed above, locale and others test language extensively, so the patch is tested well; in terms of test organization I'd prefer to do it in a followup, this is an 80k+ patch, hard to juggle.

- FOLLOWUP: language count as cache entry, makes sense, agreed on a followup

- DISCUSS: on language_save() and language_uninstall(), they don't really do the same thing; language_save() does not re-run the language initialization process, it merely clears the language cache; langugae_uninstall() does need to rerun the language initialization, because potentially removed language might have been selected before; in fact language_delete() should do that too (it only clears the language_list cache like language_save()); initializing the language system just reruns the initialization of globals, it does not clear the language list cache

- DONE: fixed @file summary

- DONE: renamed list tab

- FOLLOWUP: yes, using entity-like paths might be good here, either is fine

- FOLLOWUP: should drupal_write_record() use db merge on update anyway?

- DONE: using form_load_include()

- DONE: modified phpdoc on locale_enable() to explain this is merely syncing config with the reality of language lists; since languages and negotiation are separate with this patch (they might become one again later, depending on ongoing discussion), it is possible people remove a language and add a couple and we need to sync our config to that; as for accidentally removing language, if you remove your language, nodes in that language will turn to LANGUAGE_NONE, your UI localizations for that language will vanish, etc. so loosing your path prefix config is the least of your issues; looks node module or locale module has no grace for people accidentally removing language; they should keep backups and watch their clicks

- DONE: modified the cache operations as requested

Will post same feedback for @plach's comment and then post the patch, ups, need to change workplaces now, sorry.

gábor hojtsy’s picture

Status: Needs work » Needs review
StatusFileSize
new81.72 KB

@plach:

- DONE: moved language update to its own function

- DISCUSS: right, language is not enabled; I don't yet know how to do that, if we enable the module, we cannot do that in this early in the bootstrap phase I think, we should do it later; however, once we enable the module, the language table schema will be attempted to be recreated and its already there... because calling hook_schema is automated we cannot make it not be called AFAIR; so we need the language table/data early in the bootstrap to be able to bootstrap D8 but we cannot enable a module that early in the bootstrap, can we? and even then how do we skip the schema?

- DISCUSS(?)/FOLLOWUP(?): I changed %name to %language since more existing text used %language. It it also a more universally reusable pattern for other cases where we talk about multiple things. t('%language translation of the post has been deleted') would look odd with %name, right? So just trying to establish a common practice here; we can also use %name in language module but would need to use %language in more general settings, so it looked like it makes sense to be consistent here

- DONE: modified to "Prepare a language code list" vs. "Prepare the language code list", since its not THE language code list, its A language code list

- DONE: removed empty line

- DONE: included locale.inc in locale.enable although I'm not sure its strictly necessary there (its included otherwise already, but it does not hurt to be explicit)

- FOLLOWUP: I'd rather not deal with locale batches here, let's focus on the language module here :)

plach’s picture

right, language is not enabled; I don't yet know how to do that, if we enable the module, we cannot do that in this early in the bootstrap phase I think, we should do it later; however, once we enable the module, the language table schema will be attempted to be recreated and its already there... because calling hook_schema is automated we cannot make it not be called AFAIR; so we need the language table/data early in the bootstrap to be able to bootstrap D8 but we cannot enable a module that early in the bootstrap, can we? and even then how do we skip the schema?

Maybe update_module_enable can help us here?

included locale.inc in locale.enable although I'm not sure its strictly necessary there (its included otherwise already, but it does not hurt to be explicit)

I had to add that line to enable Locale after enabling Language separately, otherwise I got a fatal error.

I'd rather not deal with locale batches here, let's focus on the language module here :)

Well, locale_languages_add_set_batch() already exists in the current code and isolates well those three (api) lines from the submit handler code, why removing it?

gábor hojtsy’s picture

StatusFileSize
new81.93 KB

Great find with update_module_enable(), now using that. Ok on the locale.inc inclusion, thanks for all the manual testing too. For the third point, I removed it because the two submit hooks are now one and its just three lines, so adding yet another layer of functions there did not seem like its worth it for 3 lines. It did make lots of sense when it was two separate submit hooks, now its just a couple lines form_altered in. We can add it back but I don't think its needed.

Status: Needs review » Needs work

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

plach’s picture

It did make lots of sense when it was two separate submit hooks, now its just a couple lines form_altered in. We can add it back but I don't think its needed.

Well, I have an almost compulsive tendency to make submit handlers as slim and API-less as possible. I'd feel really bad to RTBC a patch moving in the opposite direction ;)

+++ b/core/includes/update.inc
@@ -100,7 +100,55 @@ function update_prepare_d8_bootstrap() {
+    if ($has_required_schema) {
+      if (db_table_exists('languages')) {

Sorry for being picky, but I'd prefer to move this test into update_prepare_d8_language(), since it implements a logic that belongs there. Otherwise having two nested ifs feels wrong.

+++ b/core/includes/update.inc
@@ -100,7 +100,55 @@ function update_prepare_d8_bootstrap() {
+  update_module_enable(array('language'));

I bet the problem with the failing tests is that system_list_reset() belongs to module.inc, which might not be included yet.

22 days to next Drupal core point release.

gábor hojtsy’s picture

Status: Needs work » Needs review
StatusFileSize
new82.76 KB

Ok, well, that function then became locale_translate_add_language_set_batch() and went into bulk.inc, so we need to include that now anyway from the submit function before calling it. Looks better? (We lost two lines in the submit handler and got an API function instead).

Moved the db_table_exists() to the language bootstrap function. I think inside or outside makes equal sense. Left the two nested ifs originally there in anticipation of other such changes needed with more ifs on the same level.

On the module.inc problem, maybe this function is not intended for this use, but as far as I can think about this, what it does makes quite lot of sense to be used in this context. Except module.inc not yet being available. The function used only uses drupal_static and cache related things, which are bootstraped by the time it is called (the bootstrap fix code bootstraps to the DB level), so just adding include for module.inc could fix this for good.

Let's look at this one!

plach’s picture

Status: Needs review » Needs work

Ok, well, that function then became locale_translate_add_language_set_batch() and went into bulk.inc, so we need to include that now anyway from the submit function before calling it. Looks better? (We lost two lines in the submit handler and got an API function instead).

Thanks for being patient with this poor old man :)

+++ b/core/includes/update.inc
@@ -100,6 +100,54 @@ function update_prepare_d8_bootstrap() {
+    update_module_enable(array('language'));

This call has no effect atm: we are trying to enable the Language module, but it is not in the system table yet. I'm afraid we need to check if the module is actually in the table and if not insert it instead of updating its status.

21 days to next Drupal core point release.

gábor hojtsy’s picture

What if we use system_rebuild_module_data() instead first? Based on code review, it seems to be runnable with just a DB bootstrap. What do you think?

plach’s picture

Yes, that sounds like a viable solution. Perhaps we should run it at the beginning of update_prepare_d8_bootstrap() to make all the following code being ready in case other situations will need this in the future. OTOH this sounds as a potentially tricky operation. Perhaps we need someone with a deeper knowledge of these internals.

fastangel’s picture

If yo use system_rebuild_module_data would be required module.inc in the beginning of update_prepare_d8_bootstrap(). Or I think so.

catch’s picture

We'd need to add update_system_rebuild_module_data() in case a future update changes the schema of the system table.

Additionally doesn't that call hook_system_info_alter() and hook_register_files_alter()? We can just remove those hook invocations from the update version though.

gábor hojtsy’s picture

@catch, @plach: ok, well, this is getting a bit out of scope here... At the stage where this code fix needs to run, we do *know* that the language module is not yet in the system table, so we can just insert it, no? Or we should track down how the core/ path change is implemented in regards to the system table, and get that run earlier and get it include the newly found modules too? This should either be simple code or code already done AFAIS.

gábor hojtsy’s picture

Status: Needs work » Needs review
StatusFileSize
new4.3 KB
new0 bytes

Talked to @catch in IRC, he underscored we should fix this generally here. Ok, well, here is an updated patch which copies the code that looks like is needed and reuses functions that look like are fine as-is. This is obviously pretty fragile to change in the future, since it uses functions from all over file.inc, common.inc, system.module, etc. Any non-update compatible changes in those functions would break the update. I've code reviewed the function tree involved and they seem to have no code that would stop them working on the update, but more sets of eyes would be needed to double check (and test).

Attached an interdiff and the complete patch.

plach’s picture

The complete patch in #53 looks actually very slim :)

Btw, maybe this is a superstupid idea but, if our concern is just not having hooks invoked during updates, wouldn't be simpler and safer if we just introduced a test on the maintanence status in module_invoke_all and drupal_alter? This would avoid us the need to rewrite tons of existing code.

This way we could introduce an update version of our code only if striclty needed, e.g. what @catch says in #51.

gábor hojtsy’s picture

StatusFileSize
new86.69 KB

Lol, yeah, it would be great if we could improve Drupal with patches of 0 bytes. Here is the big boy instead.

Status: Needs review » Needs work

The last submitted patch, language-module-55.patch, failed testing.

gábor hojtsy’s picture

Status: Needs work » Needs review
StatusFileSize
new86.94 KB

As is evident from the test results, query.inc is attempted to be loaded from the (old) D7 place, however, it moved to under core/* like the rest of the files. We need to rebuild the registry to be able to rebuild the module list because the module list rebuild code uses query.inc. Or we could alternatively deviate more in our custom update.inc version of the module rebuild, but I think we want to keep it consistent as much as possible with the "live" version of the code. The only change in this patch is in this hunk:


diff --git a/core/includes/update.inc b/core/includes/update.inc
index 289d27a..285038e 100644
--- a/core/includes/update.inc
+++ b/core/includes/update.inc
@@ -100,6 +100,61 @@ function update_prepare_d8_bootstrap() {
         'description' => $has_required_schema ? '' : 'Please update your Drupal 7 installation to the most recent ve
rsion before attempting to upgrade to Drupal 8',
       ),
     );
+    if ($has_required_schema) {
+      // Rebuild registry and module list to be able to bootstrap. The registry
+      // needs to be rebuilt first because rebuilding the module list requires
+      // DB classes, which will not be found based on the D7 registry given
+      // the moved files.
+      registry_update();
+      update_system_rebuild_module_data();
+
+      // Update the environment for the language bootstrap if needed.
+      update_prepare_d8_language();
+    }
+  }
+}
gábor hojtsy’s picture

Ok, feedback please!

gábor hojtsy’s picture

StatusFileSize
new83.6 KB
new5.73 KB

Got some feedback from catch on IRC that I should instead do what I originally wanted and just insert the language module in the system table instead of trying to invoke a family of functions that we need to duplicate just to get the exact right value. The system table is refreshed later at the end of the update anyway. Here is an interdiff (custom update versions of functions removed, custom SQL code against system table added) and the full patch.

Status: Needs review » Needs work
Issue tags: -D8MI

The last submitted patch, language-module-59.patch, failed testing.

gábor hojtsy’s picture

Status: Needs work » Needs review
Issue tags: +D8MI

#59: language-module-59.patch queued for re-testing.

gábor hojtsy’s picture

Don't know why it could not install. This was the testbot output:

[06:39:10] Invoking operation [install]...
[06:39:12] Encountered error on [install], details:
array (
  '@reason' => 'Installing: failed to complete installation by setting admin username/password/etc.',
)
[06:39:12] Review complete. test_id=202938 result code=7 details=Array
(
    [@reason] => Installing: failed to complete installation by setting admin username/password/etc.
)

I can install locally, so asked for a retest.

gábor hojtsy’s picture

And it does pass tests now for the second round, it must have been a testbot glitch. Reviews please!

catch’s picture

Looks like generally we are just moving stuff from locale into the new module, and renaming things for the new module namespace (colloquial namespace, not PHP5 one ;).

Wondered about a helper function for the {system} table priming since we might have this same problem again in the 8.x cycle.

This could do with an issue summary to explain what some of the more obvious changes are (i.e. there's a schema change).

Patch is missing a hook_help() for admin/help/#language - all modules have fairly standardized overview text in hook_help() after a major clean-up in 7.x and we should stick with that pattern.

Leaving at CNR for others to have a look as well.

plach’s picture

Could not test the latest patch as my dev environment broke. Currently resinstalling it, however I was going to propose the same as catch about reusing the system table priming code, something like:

<?php
/**
 * Insert module data, so we can enable the module.
 *
 * Calling a full module list rebuild so early is costly and complex, so we just
 * have a stop-gap.
 */
function update_module_install($modules) {
  $query = db_insert('system');
  $info_defaults = array(
    'dependencies' => array(),
    'description' => '',
    'package' => 'Other',
    'version' => NULL,
    'php' => DRUPAL_MINIMUM_PHP,
    'files' => array(),
    'bootstrap' => 0,
  );

  foreach ($modules as $module) {
    $module_info = drupal_parse_info_file("core/modules/$module/$module.info");
    $query
      ->fields(array(
        'filename' => "core/modules/$module/$module.module",
        'name' => $module,
        'type' => 'module',
        'status' => 0,
        'bootstrap' => 0,
        'schema_version' => -1,
        'weight' => 0,
        'info' => serialize($module_info + $info_defaults),
      ));
  }

  $query->execute();
}
?>
gábor hojtsy’s picture

@plach: well, it would only actually make the module installed if you also call update_module_enable() at the end. I agree such a utility function will be useful.

gábor hojtsy’s picture

StatusFileSize
new3.93 KB
new84.84 KB

Here is an updated patch (and interdiff) for the hook_help() improvement and the new added API for module installs.

plach’s picture

Wow, I had no time to reply to #66 :)

IMO keeping the functions separated would be more useful, as one might want to just install the module, perform some actions and then enable it.

gábor hojtsy’s picture

@plach: if the schema version is -1 and/or the status is 0, the module is not installed :) If the schema version is -1 for a module, it was never installed on this Drupal site before. Maybe you are looking for an update_module_insert_in_system_table()? :) Install would be a misleading name entirely if the module is not in fact installed.

plach’s picture

Maybe you are looking for an update_module_insert_in_system_table()

Yes, that one, just a shorter name :)

I just completed my installation, I'm almost there

gábor hojtsy’s picture

StatusFileSize
new84.83 KB
new1.48 KB

Ok, update_module_add_to_system() then. If someone has a better idea please let me know. I think its pretty much unrelated to what we actually do in this patch and people can rename it later, so IMHO we should not obsess much with it :) It will be used pretty sparingly I'd hope/guess.

plach’s picture

Status: Needs review » Needs work

Yippeee! I manually tested also the upgrade and it actually works! I'm almost ready to RTBC this, although I'd be happier if @sun had a last look to it to see if he's happy too.

+++ b/core/includes/update.inc
@@ -100,6 +100,90 @@ function update_prepare_d8_bootstrap() {
+    update_module_add_to_system(array('language'));
+    update_module_enable(array('language'));

Feel free to tell me to f**k off, but how about using a $modules variable here instead of instantiating two arrays?

+++ b/core/includes/update.inc
@@ -100,6 +100,90 @@ function update_prepare_d8_bootstrap() {
+      ->fields(array(
+        'filename' => 'core/modules/' . $module . '/' . $module . '.module',
+        'name' => $module,
+        'type' => 'module',
+        'status' => 0,
+        'bootstrap' => 0,
+        'schema_version' => -1,
+        'weight' => 0,
+        'info' => serialize($module_info + $info_defaults),
+      ))
+      ->execute();

I think we can use the multiple insert syntax proposed in #65 here. This would save us some queries when adding multiple modules.

+++ b/core/modules/locale/locale.bulk.inc
@@ -167,6 +168,17 @@ function locale_translate_export_po_form_submit($form, &$form_state) {
+  // See if we have language files to import for the newly added
+  // language, collect and import them.

Wrong comment wrapping.

13 days to next Drupal core point release.

gábor hojtsy’s picture

Status: Needs work » Needs review
StatusFileSize
new21.96 KB
new100.6 KB

I'd prefer to have an easier to read code base for these run-once update functions compared to abstracting them to perfection, since upgrades are a critical part of Drupal that people struggle with sometimes. Anyway, I made the $modules = array() addition. I don't think your proposed multi-insert syntax would work, at least the docs for multi-insert say we should call fields() with a list of fields, and then repeatedly call values() (not fields()) with the values for those fields. All-in-all I think that also makes this code less readable for a performance increase that would probably be negligible. Fixed the comment wrapping as well.

I also went in and added a language.test based on the first test case in locale.module. It tests adding a predefined language, a custom language, changing default languages, enabled/disabled status, removing language (including English) etc. So it basically covers the whole UI of the language module. I cut down on this original test in locale module and instead concentrated there to the negotiation path prefix autoconfiguration that is happening there, so it got much better test coverage there now. This also surfaced a bad condition in language_list() on locale module, so it was a great thing to do here after all. (Not as a followup). I think this should satisfy @sun's concerns from above and prove that the language module works in itself as well. We'll continue with cleaning up the related pieces in followup patches as noted above, so let's get another look on this and get it in! (It is past 100k with the tests, eh).

Thanks!

plach’s picture

I don't think your proposed multi-insert syntax would work, at least the docs for multi-insert say we should call fields() with a list of fields, and then repeatedly call values() (not fields()) with the values for those fields. All-in-all I think that also makes this code less readable for a performance increase that would probably be negligible.

Ok, works for me.

The patch looks good, has been manually tested (regular usage and upgrade), now has even test coverage, so I'd say it's ready. I have only one concern: I just realized we are introducing a new permission, should we handle it in the upgrade code?

gábor hojtsy’s picture

The permission is merely moved from locale module, see the locale.module hunks... It is not at all new.

plach’s picture

Status: Needs review » Reviewed & tested by the community

Right, RTBC then :)

sun’s picture

Issue tags: +API clean-up

Cleaning up bogus/duplicate "API cleanup" term.

sun’s picture

Excellent, looks good to me.

dries’s picture

This looks good to me too, although it is not 100% clear why we want to make this a separate module. It's better for developers, but I'm not sure it is better for site builders (site assemblers). Arguably, this adds complexity in the UI. I thought we had originally decided to make language.module required for all sites. That would have eliminated that argument. Thoughts on that?

gábor hojtsy’s picture

@Dries: I can assure you that establishing a standalone language module did not come out of thin air. There is a very detailed conversation about how to organize language functionality in #1293304: Break up locale.module, but how?, which has a 100+ discussion history of the past three months. I suggest you look at especially the use cases outlined in http://drupal.org/node/1293304#comment-5053640 and below, with real Drupal site examples and functionality breakdowns showing among others, sites where language assignment functionality is all you need. I also have detailed examples for why it is not possible to have a one-stop module solution for "the language problem" at http://drupal.org/node/1293304#comment-5329604.

There is plenty of feedback all around on that issue and in related discussions and the general feedback was that people don't want yet another required core module for them. This was discussed more at the start of that discussion, eg. see catch's summary in http://drupal.org/node/1293304#comment-5049546. In short, people suggested if we make it required, we make it so it use lazy loaded classes and other great new things that we still don't have an infrastructure for in Drupal 8 yet. That could be a fine next step to improve the UX even more later and I don't believe we should block this improvement on that.

catch’s picture

We have a complex modules UI, there's a very long thread dedicated to redesigning it at #538904: D8UX: Redesign Modules Page, and it's identified as a major priority for Drupal 8 by Bojhan and yoroy. Having more modules rather than less definitely exposes how poorly equipped the current modules UI is, however I don't think we can blame that on dividing up modules themselves. It's a wider problem that can't be tackled without fixing the overall module system and interface.

If there are things that we can refactor into classes then it's worth looking at doing that, but a lot of the discussion on how to handle this is still in the works, so I'm personally happy to commit patches that decouple unnecessarily decoupled code, since a lot of that work would need to be done for a more complete refactoring anyway.

Additionally we currently have no way for plugins to specify a database schema, so in this case it would depend on either CMI or system module to provide language storage. We seriously need to get away from system.module being a dumping bin of subsystem schemas and rats nest of interdependencies, and CMI isn't available yet.

I would be very much against making this a required module, we have a dependency management system so the module will be enabled automatically on sites that definitely need it. Having more required modules works directly against the aims of #1373142: Use the Testing profile. Speed up testbot by 50% to increase the speed of our functional tests, and the only difference between a required module and an optional one in Drupal 7 and 8 is whether checkboxes on the modules page are disabled or not - you still get them in the modules UI, help pages etc.

sun’s picture

Whether language.module is going to be required or not, whether it's going to be exposed in the UI, or not, is a discussion and decision that can be re-iterated very easily and can happen completely independently from this patch.

Let's make progress instead. This change still belongs to D8MI's clean-up work, but is a hard dependency, so we still don't have any "real" progress to show to the world.

@catch: As I believe that @Dries is unavailable for the next days and hasn't raised any other concern than this, can you go ahead?

catch’s picture

@sun, I'm not planning to commit this until we're under major bug thresholds again.

webchick’s picture

Back from vacation! Major bug queue status: decimated! :D

We'll be under major task thresholds too if this gets committed. :)

catch’s picture

Title: Move language listing functionality from locale.module to a new language.module » Change notification for: Move language listing functionality from locale.module to a new language.module
Priority: Major » Critical
Status: Reviewed & tested by the community » Active

OK, committed/pushed to 8.x. I don't think Dries' concern is a showstopper, and this feels like a good step towards where we want to get to me.

Looking forward to the follow-ups!

This will need a change notification.

gábor hojtsy’s picture

Title: Change notification for: Move language listing functionality from locale.module to a new language.module » Move language listing functionality from locale.module to a new language.module
Priority: Critical » Major
Status: Active » Fixed
gábor hojtsy’s picture

Followups being worked on:

- #1387586: Rename drupal_multilingual() to language_multilingual() (IMHO Novice, need to figure out the best name :)
- #1387608: Unify language_list() and locale_language_list() (badly needed, removes one of the two remaining language object related functions from locale, IMHO Novice again)
- #1357918: Missing update for language_default in language langcode update
- #1357912: Convert path language code schema to langcode (related to above)

See you at these places!

Status: Fixed » Closed (fixed)

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

gábor hojtsy’s picture

Issue tags: +language-base

Tagging for base language system.

gábor hojtsy’s picture

Minor followup: we left the API docs in locale.api.php too when the ones were moved to language.api.php. The locale.api.php items should be removed. See #1470080: Nothing in locale.api.php belongs there.

batigolix’s picture

In #2103039: Review hook_help for the language module we review the hook_help text that has its origin in this issue.
Linking them together as related.