Consider the following scenario:
(1) create two drupal sites, etsource.localhost and etdest.localhost
(2) on both, enable locale and language, go to admin/config/regional/language, and install and enable French in addition to English.
(3) on etsource, download and enable the features module
(4) on etsource, create a content type x
(5) on etsource, go to admin/structure/features/create, create a new feature with the content type x
(6) now put the module x in etsource and etdest, in the sites/all/modules folder
(7) enable x on both etsource and etdest
(8) on etdest, node/add/x, and enter "created with untranslatable field" as a title and body: this will be etdest/node/1
(9) on etsource and etdest, dowload and enable entity_translation
(10) go back to etsource.localhost/admin/structure/types/manage/x/fields/body, click "users may translate this field" and hit save
(11) go to http://etsouce.localhost/admin/structure/features/x/recreate, add entity_translation as a dependency and save
(12) put the new version of x on etdest
(13) on both source and dest, revert the feature
(14) on etdest, node/add/x, and enter "created with translatable field" as a title and body: this will be etdest/node/2
(15) update the feature again to reset the body field to untranslatable, and deploy.
(16) on etdest, create node/3 with the title and body "created with untranslatable field again".
node/1: you see the content
node/1/edit: you see the content in the body field
node/2: you don't the content
node/2/edit: you don't see the content in the body field
node/3: you see the content
node/3/edit: you see the content in the body field
When deploying new field translatability, an api function in entity_translation might be good, so we could do something like:
function x_update_7001() {
// this function does not exist!
entity_translation_update_field_data('body');
}
For now it seems that the function that does this is really tied to the batch process and the form, so there is no clear way to do this programmatically.
Comment | File | Size | Author |
---|---|---|---|
#15 | entity_translation-1916712-15.patch | 2.91 KB | jcisio |
| |||
#15 | entity_translation-1916712-15-interdiff.txt | 505 bytes | jcisio |
#14 | entity_translation-1916712-14-reroll-of-9.patch | 2.84 KB | donquixote |
|
Comments
Comment #1
alberto56 CreditAttribution: alberto56 commentedIn the above scenario, the database is in this state:
If the field should be LANGUAGE_NONE, we would need the function to update the language of line two of the above, it seems. That way, if a field is being modified during a deployment, our function could make sure the above table would be in a consistent state.
Comment #2
alberto56 CreditAttribution: alberto56 commentedTo normalize the data in this table, I used the following code. What I have in mind for entity_translation_update_field_data() is a more robust version of this:
Comment #3
bforchhammer CreditAttribution: bforchhammer commentedYes, having something like
entity_translation_update_field_data()
would be useful for automatic data migration tasks. Ideally that function would also be used by the existing batch process in order to avoid duplicate code/logic.However, until we get there, note that it should also be possible to use the batch process from within your update function by reusing the hook_update-batch sandbox. I had a very similar problem a while ago, see code below. Maybe it can help you avoid having to update the database yourself... Note that I wrote this about a year ago for the old alpha version of ET, so no guarantee that it still works. :-)
Also note that if you want to use this for multiple fields, I found that you had to use a separate hook_update for each field or otherwise the batch process would get stuck.
When you start converting an existing site to use ET you probably also want to start using the title module; here's the snippet I used for migrating old node titles to title module ones.
Hope this helps. :)
Comment #4
alberto56 CreditAttribution: alberto56 commentedThanks, very useful indeed!
Albert.
Comment #5
alberto56 CreditAttribution: alberto56 commentedIf one is updating a field from untranslatable to translatable one a single site, the confirmation text warns you that you will be losing data. The same is not true if you are deploying a change -- so it might be prudent to not implement the exact same code: for a deployment, perhaps keeping a copy of the translations might be a good idea in case the field is again set to translatable.
Comment #6
pbuyle CreditAttribution: pbuyle commentedUber-useful.
Starting from #3, I wrote a unique hook_update_N() to process all translatable fields, it can be found at https://gist.github.com/pbuyle/51d30e80a17920f6df12.
Comment #7
fago>Uber-useful.
Indeed!
That works already pretty good - thanks. I just had to make a few small adjustments to make it work for me. I think the update so far is written fine already and can be added to the module. Thus based on that, here is patch which does so.
Comment #8
fagoops, corrected example code in the docs.
Comment #9
fagoand to make it a bit clearer...
Comment #10
donquixote CreditAttribution: donquixote commentedThis approach has a problem.
When running the batch BEFORE the respective feature is reverted, it causes data loss and will misbehave.
To be more precise:
if the field is still configured as not translatable, but you run the batch with $translatable = TRUE, then field_sql_storage_field_storage_write() will discard all the language-specific values, while the language-neutral items will be deleted.
Comment #11
donquixote CreditAttribution: donquixote commentedPerhaps better would be to provide a drush command, and/or another version of the UI page that does not switch the translatability but only updates the field items according to the current setting.
Comment #12
jcisio CreditAttribution: jcisio as a volunteer and at Axess Open Web Services commentedRe #10: I don't see why patch #9 is a problem. It gives just a function to migrate all data for translatable fields and can be used anywhere if
$sandbox
is provided. So in a hook_update_N, a features_revert() should be called first. But if it is not called, there is no problem because untranslatable fields are not migrated.Comment #13
donquixote CreditAttribution: donquixote commentedRe #12
You are right.
Calling
entity_translation_translatable_batch()
explicitly from your 3rd party code can cause damage, if you are passing the wrong value at the wrong time for the $translatable parameter.Calling
entity_translation_migrate_field_content_update()
from 3rd party code does not do damage, because it has no $translatable parameter.The worst thing that can happen in this case is that the migration never happens, because the calling code runs in the wrong order. This in itself does not damage existing content, it could be fixed with a follow-up second attempt at updating.
Perhaps having the field in a non-updated state could cause damage over time from other operations, not sure.
Also, a caller might be tempted to pass the field name and field info explicitly to the function via $sandbox['fields'], to avoid that all fields are being processed even though their translatability has not recently changed. This could have the same problem as calling entity_translation_translatable_batch() with the wrong $translatable parameter at the wrong time.
Note that with all of these problems we could simply blame the calling code, they should be more careful.
But imo we should always try to make it hard to use an API in a wrong or destructive way.
Also note that this function only works for one direction of the conversion. I assume we also need an update operation to make a field untranslatable?
This is not really advertised on this function, is it?
I have seen "deployment instructions" for custom code where a "drush fr NAME" and "drush updb" had to be called in a specific order. Something I would rather avoid. So calling the features_revert() from the updb seems like a good idea, but it should be documented.
Comment #14
donquixote CreditAttribution: donquixote commentedIf we advance this patch, it also needs a reroll and then some code style fixes.
Attached is a pure reroll after fixing a trivial conflict. No CS fixes.
Comment #15
jcisio CreditAttribution: jcisio as a volunteer and at Axess Open Web Services commentedNo CS fix. Just add features_revert() in the docblock because I think it's the only important point.