Here is a simple solution to add node translation to Drupal core, majority of work by Jose A Reyero.
Let me point out straight that we are only thinking in terms of node copies for this release cycle, no direct solution for shared data among nodes. With different node instances for translations, people could have comments, revisions, authors, workflows, views, etc. differently for translations. Those wishing shared data between nodes, but are not interested in having standalone node instances can take a look at our 'object translation' feature, which can be finely used to provide translation with shared data for nodes (but without the possibility to have different workflows, authors, revisions, etc). The object translation feature needs so many core modifications that we are concentrating on that first, instead of being able to shared fields between node translation instances (which we believe is a CCK-level feature requirement). It should also be pointed out however, that there is nothing here to prevent from a contributed module to implement shared fields, we just prefill fields initially, and allow other modules to hook into our processes and do whatever they wish.
So the attached patch does the following:
1. Introduction of translation sets. A node can be part of one translation set, of which the first associated node is regarded as a "source node".
2. Nodes have their "translation source revision" stored in the translation set, so if the source node has a new revision created, we can inform translators that their translations are outdated. Now if a translation node is modified, it is marked as being fully updated to the actual source node, which might not be the case in real life with translation modifications. Contributed modules can hook into the node form to alter this behavior, providing controls to the user to tell the code what is really updated in the text.
3. On the UI, we add a translation tab on nodes where language is enabled and the node itself is not language neutral. This tab shows an overview page, which allows creation of new translations as well as overview of existing translations.
4. Nodes get "translation links" in the node links array, so users can switch to different language versions. This is of course themeable.
5. When a new translation node is created, body and title are prefilled with the source body and title. We have a nodeapi extension in place for other modules to prefill other fields of translation nodes.
The following TODOs are in the code, which need some discussion:
* An option to toggle translation links for content types? Like we have toggles for author info.
* Native names for languages in node links? Or translated names in the language used, or both? Now we have translated links. Only themers can alter that now.
* Help text and documentation! Obviously we need docs for the "translate" tab, once basic things are settled.
* New content type setting, to enable translation per node type? Like we have "language enabled" node types now.
* What if we want to add an existing node to a translation set? hook_nodeapi() update and delete operations are ready for this, but we have no UI yet. This might be interesting for people upgrading, maybe having nodes which were in fact translations of each other but never marked as such. Otherwise i18n module and localizer module will need to provide their upgrade scripts to users.
* Admin overview interface for translations not included, because unfortunately it is mostly copy-paste of the node admin overview (which is not modular enough yet). Maybe Roberto Gerola has something to share in this front, but that can definitely be a separate patch.
Note, that this patch puts translation module into node module's folder because I was unable to find out how to do a patch with adding a new directory (cvs diff was throwing lock errors at me). Of course the final place of translation module will be a dedicated folder, but for testing and review, this is fine.
Let's first decide if Drupal 6 needs such a built-in module at all, or should we postpone it for Drupal 7 and/or a contributed module altogether! We have a lot of issues on our hands, lot of stuff to get completed in the Drupal 6 timeframe on the multilanguage front, so we'd better concentrate on what is likely to get enough acceptance.
| Comment | File | Size | Author |
|---|---|---|---|
| #57 | translation_module_10.patch | 21.68 KB | yched |
| #55 | translation_module_09.patch | 22.59 KB | yched |
| #50 | translation_module_08.patch | 23.26 KB | gábor hojtsy |
| #44 | translation_module_07.patch | 21.73 KB | gábor hojtsy |
| #34 | translation_module_06.patch | 17.36 KB | yched |
Comments
Comment #1
jose reyero commentedsubscribing
Comment #2
moshe weitzman commentedyes, we really really want this in 6. so lets work to get it ready. if we run out of time, we should seriously consider making an extension for this patch. thats not so uncommon. the described approach sounds sane.
as for the admin interface, i am hoping to write a Views powered node management page. See http://drupal.org/node/125810. Maybe we just leave the admin UI in Contrib?
Comment #3
jose reyero commentedMoshe,
Yes, I will be including the parts of this that don't get into Drupal core for next version into i18n.module
We have some work done for the admin interface, you can check it out here http://svn3.cvsdude.com/devseed/sandbox/i18n/
But that solution won't scale well for a big number of languages so we are looking for something better
Comment #4
gábor hojtsyJose, Moshe referred to extending the time to the code freeze period, which IMHO only would be logical, if we would actually get reviews of this patch. An important patch sitting there without reviews might not be a good reason to extend. Anyway, that will be up to Dries to decide.
Moshe, we do have a simple admin interface for this already, but that is in a big part a copy of the node admin overview interface. Unfortunately that code is not reusable enough. But Roberto Gerola did show us some good looking changes to make that more extendable, but did not pushed that patch forward for whatever reason... Hm...
Comment #5
dries commentedI agree -- this is something we want for D6. It's at the core of what people expect us to deliver.
* An option to toggle translation links for content types? Like we have toggles for author info.
This could be added later.
* Native names for languages in node links? Or translated names in the language used, or both? Now we have translated links. Only themers can alter that now.
Not sure I understand the difference between 'native names' and 'translated names', but the names should always be in the native language (assuming 'native language' means the visitor's language). If you go to a Chinese website, and it has an English translation available, it shouldn't communicate that in Chinese. You want to recognize the word 'English' somewhere, or you would not be able to figure out how to proceed.
* Help text and documentation! Obviously we need docs for the "translate" tab, once basic things are settled.
Yep.
* New content type setting, to enable translation per node type? Like we have "language enabled" node types now.
Does that need a new setting, or can we reuse the existing setting?
In the patch, what does the 's' of 'svid' stand for?
I'm wondering why we need the translation sets -- can't we just add a field to the node table that keep the nid of the source node?
Comment #6
owen barton commentedSubscribing
Comment #7
gábor hojtsyDries,
- toggle translation links: OK
- native names: you understand it right, we mean that "English" would be printed on the Chinese page (now the Chinese name of English is printed)
- help text: sure
- translation setting: we can have a setting on node types (a) language and translation enable this node (b) language enable this node (c) save these nodes in the default language always; (currently (b) and (c) are already there); this makes sense, because translation enabling a node type has no use if it is not language enabled
The svid stores the source node revision ID which the translation is updated to. The idea of translation sets comprised of a source node and translation nodes brings us two things: (a) we can have a fallback for shared fields, if a contributed module is about to exploit this possibility (b) we can track what source revision number is the translation updated to. So if the original document is updated, we compare the svid of the translation node with the current vid of the source node, and we see that there is a difference, so the translation needs updating. Neither i18n nor localizer module tracks revision numbers now. If we would store the nid of the source node in the node table itself, we would not be able to track revisions.
So what we store is: (translation set id, node id, node revision of this node, source node revision id for which this node is up to date). Now for easy querying, the translation set ID equals the source node ID. So this table relates nodes to each other as translations *and* relates node revisions of these nodes so we can check for up to date and outdated content based on revisions.
This patch has no direct support for shared fields, and it has no direct support for the user to set an edit of a node as being a translation update (so we need to advance it as being updated to the latest source revision), or only being a small fix, or being an intermediary update to some earlier source node revision. Contributed modules can implement the later functionality by form altering, possibility the first functionality is also there, but it will need more contrib magic.
So basically with translation sets, we open two cool possibilities. By storing the nid relations in the node table itself, we could simplify the code a lot, and would get it in sooner :) but would loose two possible cool contrib features.
Comment #8
gábor hojtsyHere is a quick figure to illustrate the point. So for one we store what nodes as in a set, and we also store what revisions of these nodes are related. Now on the figure, we can see that the source node has a new revision, and we see that the translation node is not updated to that revision, so we know that the translation is outdated. By using only the timestamp, we would not be able to accurately tell this. Although the core module we propose does work the same as if we would use the timestamp, it makes it possible (via form alter) for a contrib module to provide better tracking of revisions. So we have the code and the database there, but not the UI. (Because we don't think such an UI belongs in there now).
If we decide that this feature is not required now, we can pull the revision relations now, and get the node relations in sooner. It would greatly simplify the code :)
Comment #9
meba commentedReviewed and seems to work. Please note that you have to enable Content translation module for this.
One bug: Create a node, add translation. Then view your translation and click Edit. Language selection box will have "Language neutral" instead of "My language"
Comment #10
dries commentedBy tying translations to revisions, you impose a hidden workflow. In other words: if you want the translations to be marked as 'out of sync', you need to create a new revision. If you don't want the translations to be marked as 'out of sync', you can't create a new revision. That might cause problems as I might want to update a node, create a new revision and not mark the translations as 'out-of-sync'. From what I understand, this would be impossible with the proposed module.
Furthermore, it requires that the author know the revision system. Many site don't care about keeping revisions, and that's perfectly valid, IMO.
Personally, I prefer an approach that is both more transparent, more flexible and more explicit. Just add a check box "mark translations as out of date" and keep a flag.
So why not a source node and an extra flag/status field to mark the node as up-to-date.
Comment #11
jose reyero commentedReworked a big part of the module.
- Removed all the vid related information. New fields are 'snid' for source node and 'status' (default 0, will be 1 if translation needs updating)
- Followed Dries remarks about 'hidden translation workflow'. Now there are some settings in the node form
a) If the node is the translation source, there will be an option to mark all the translations as 'need updating'
b) If the node is not the source, the 'status' field will be shown, asking whether the translation must be marked as outdated or not.
- Fixed the bug mentioned by meba in #9
- Node links with native names
- Added db_rewrite_sql for the query loading translations
Note that we are now keeping track of the translation source at two levels: the first source nid will be the translation id (trid), while we still store the source that has been used for each specific translation. Why? Because it is easy, it keeps all the information about what has been translated from what and the info is just there if someone else needs some more complex translation workflow.
So, I guess this may need some more work yet, but I think the most important issue is to find some solution for that translation workflow. Please, feedback.
Comment #12
yched commentedIs it normal ?
- one 'english node', with an associated 'french' translation node
- editing the nodes, I don't have the ability to change their language, but I can set them to 'language neutral' ?
Additionnally, if I do set the english node back to 'neutral', it still shows a link to the french node - and the french node displays an 'undefined index warning (translation.module line 134)
Comment #13
webchickI created a node with French content, and then clicked Translate to make an English version. That worked fine.
Then I edited the French version of the node and made it Language neutral.
1) The Translate tab went away.
2) The English link remained.
3) When clicking the English link, or on teaser view, get:
4) Translate tab is active on the English version. I click it, and I can add a new French translation.
5) Now the original language neutral patch shows both French and English links.
6) So, naturally, I went back to the now Language Neutral version ;) and attempted to change its language. Language Neutral is the only choice there, so that's good.
7) I delete the original "parent" node. The two translations remain. not sure if this is "by design" or not.
And this, folks, is why evil webchick shouldn't test patches. ;) I will try and test something non-edge-casey now. :P I don't even know if this is helpful, although that notice should probably be fixed. ;)
Comment #14
davemybes commentedThis isn't exactly a bug, so I apologize if this is the wrong place to post this. However, seeing as its related to this patch I though it would be OK here.
I was wondering if the "select node" option for translations is still on the cards? Its extremely useful - I might even go so far as to say critical. Should we submit a patch to the latest patch for this, or should we hold off for a while.
Comment #15
webchickPolls:
1) Created a French poll.
2) Clicked "Translate"
3) BUG: The title is pre-filled with French content, but the choices are not.
4) BUG: I vote on the English side, this is not reflected on the French side.
(note: there are also a bunch of notices, but those are there without the patch.)
Comment #16
webchick#15 brought up an interesting philosophical discussion between yched and myself... ;)
Is #4 actually a bug?
On a Canadian site, you probably want the poll data aggregated; although you have French and English content, most of your audience will intermix regardless of language.
On an "international" site, your French/English/Japanese members might be cordoned off in their own areas and not even know the other exists. In that case, it doesn't make sense for the English poll to increment when a Japanese visitor votes.
It seems we need the ability to configure how this works... we talked about enabling an "Aggregate content" option per node type, but that's ambiguous, since comment-enabled types will do one type of thing, voting-enabled types another, and polls something different again.
Comment #17
David Lesieur commentedAbout the [lack of] sharing of data between nodes: Gábor's above explanations for the initial patch (#0) would mean that #15.4 is not a bug. :-)
Comment #18
yched commentednew patch fixes the bug described in #12 - #13 : setting back to 'language neutral' keeps the node in the translation set (and leaves inconsistent state)
+ fixes some
} else {code style 'bugs'.Comment #19
yched commentedwait, this is no good - dlesieur pointed on IRC that if we remove the 'source' node from the translation set, we have to pick a new 'source' amongst the remaining ones...
Comment #20
yched commentedActually this is even a little more tricky :
the nodes in the translation set do not necessarily have the 'mother node' (nid = trid) as a source (snid)...
Say English (1) is mother
Create French (2) from English
Create German (3) from French
trid = English , French snid = English, German snid = French...
remove French, and you have to update German...
Which leads me to : Do we _really_ have to keep distinct concepts of trid and snid ?
Anyway, updated patch, tries to handle 'node removal' nicely with the current state of trid and snid :
- sets a new 'mother' (trid) for the translation set if the current 'mother' is removed,
- sets a new source for the nodes that had the removed node as source.
See the patch, and talk about convoluted code / logic... Suggestions / simplifications welcome
Comment #21
yched commentedand prevent 'single node' translation sets...
I guess this will be all for tonight.
Comment #22
gábor hojtsywebchick: In #16, you perfectly explain why it might not be a good idea to force data sharing among translations. As I explained, this patch does not include any data sharing whatsoever, although it could be logical for votes, node attachments, event dates, for some people even comments and so on. Sharing these might be required for node types on a site by site basis, maybe even on a node-by-node basis (some nodes might share their attachments with translators, some might not). So this is not really something targeted for Drupal 6 core (although contrib modules will be able to implement it just fine).
Also, translation module by itself tries to prefill the title and body fields. If a module defines other fields, it should go in with hooks and prefill the values.
+ // Let every module add translated fields.
+ node_invoke_nodeapi($node, 'prepare translation');
This new nodeapi hook is not yet implemented in poll module.
Comment #23
meba commentedReviewed and didn't find any bugs
Comment #24
gábor hojtsyHm, I also wonder what use do we have in keeping both trid and snid? Although it makes it possible to have "translations of translations", I don't think it is a good idea to encourage that. It also makes our relation structure overly complicated.
Additionaly to this, I am also not comfortable with supporting the setting of a translation set member to "language neutral" to remove it from the translation set (or for any other reason whatsoever). A member of a translation set should not be language neutral. If the set needs to be modified (a node added or removed from it), that should be done on the set overview page, not via magic side effects of language settings, as far as I see.
Comment #25
David Lesieur commentedSome usability remarks that came up during the last Montreal Drupal Meetup:
Comment #26
gábor hojtsyI discussed this issue with Jose briefly, and he indicated that he is busy with other issues requiring core level changes (although not as shiny new features as this one is). So it would be nice if others could bring this patch forward. The developments by yched are looking in a fine direction, but as pointed out, we can simplify this patch. Please keep up the work, Drupal 6 should have this in! :)
Comment #27
mgiffordWanted to quickly say that I tested this patch here:
http://drupal6.dev.openconcept.ca/?q=english_example
and liked how it functions. Quite similar in many ways to the current i18n module. Would love to see this module brought into core.
I was at first confused about applying the patch for this module as the files didn't exist. Anyways, created the directory and then applied:
patch -u < translation_module_04.patch
I liked the "This translation needs to be updated" feature. Would certainly be nice to have other items listed under the "Translation settings" such as - original language.
Mike
Comment #28
gábor hojtsyLet me repeat that Jose is not going to work on this patch unfortunately in the remaining few days, so it would be nice if those already involved with the patch could pick it up. It would be important for Drupal 6. Let's solve the TODO items in the code and raised by people so far:
- let trid = snid, so we don't need both of them, and it is not going to be confusing => Dries suggested that we can add the trsnid and trstatus fields to the node table (maybe with more creative names :)
- Dries indicated that the node language selector should be extended to a three way selector: (default language, node language support, node translation support), the third being inclusive of the second option (we already have the first two options there, just need to form alter)
- improve the translations screen with some help text
This is a really short list and as far as I see, we are quite close. As discussed, we can skip the other TODOs in the code (a dedicated translations overview page, options to toggle translation link visibility, putting existing nodes into a translation set) and go forward without them being implemented for now.
Comment #29
yched commented@Gabor : I heard you plea here, and I guess having rolled a debug for this patch makes me the one who should stand up here.
I'm quite willing to do so, unfortunately there's absolutely no way for me to make it happen before late thu. 31 at best :-(. If anyone else is ready to pick it up before that - please do !
Also, I'm not sure I understand the thing about a 'three way selector' for node language ?
Comment #30
gábor hojtsy@yched: that would still be much better then nothing, and greatly appreciated. :) I will consult with Dries then if we could have this patch in even if it slips the final date with a day or two.
About the 'three way selector', now we have this setting on a content type if locale module is enabled
Now translation modules enabled *all* node types with multilingual support to have translations. This is probably not required on most sites. Like you would like to have your pages translated, but not your blog posts. So this would become:
This way you could have nodes with language but without translation support, so content authors are not distracted with translation controls where they should not appear.
Comment #31
gábor hojtsyOf course translation module would form_alter() what locale module form_alter()ed into the content type config form.
Comment #32
yched commentedGot it :-)
I'll try to post an updated patch (well, module) in 2 or 3 days if noone beats me to it.
Comment #33
yched commentedOk, here is an updated patch, as promised (and not sooner than promised, but we're still in May in France :-) ).
- trid = snid, so we keep only the snid
- removed the {translation} table, the two translation fields live in {node}
- added a 3rd option for content types settings ('multilingual, with translations')
(sorry, still 1 todo : update the '#description' for the radios accordingly.)
- I also made clearer on the translation overview which node (which language) is the 'source' node.
Comment #34
yched commentedPrevious patch was missing node.module.
Comment #35
gábor hojtsyDone a quick code review:
- The 'snid' and 'tr_status' columns should somehow have more similar names, belonging to the same feature set... I like 'tr_snid' and 'tr_status' or simply 'tr_nid' and 'tr_status', but Dries might argue and have simpler ideas...
- Your node.schema changes have tabs
- I think the @todo comments on the file level can be removed, we know we need help text, the other ones are implemented
- Indeed, we need an updated description on the node language field
- Looking at the nodeapi, it still seems to stand that we can remove a node from a translation set by setting it to 'language neutral'... I'd think this is a misfeature, or rather a bug... A node in a translation set should always have some meaningful language attached, and removing it from the set should be an explicit action as far as I see. "Action links" on the translation overview page for each node to remove it from the set seems to be more logical (and the "language neutral" option should be removed when editing a node which is in a translation set).
Otherwise this module looks good, thanks for picking it up yched!
Comment #36
dries commentedSo this is not really something targeted for Drupal 6 core (although contrib modules will be able to implement it just fine).
This appears to be an essential feature. Having to re-enter dates, telephone numbers, or whatnot can be a real pain for the user. Being able to share fields seems key to provide a good user experience towards content editors?
Comment #37
yched commentedDries: with the current patch, it is currently up to each module to pre-fill the node form elements they control with the values from the source node when creating a new translation (
hook_nodeapi('prepare translation')).Provided CCK implements this behaviour, I think this is a good compromise.
Besides, I'm not sure how we could 'automate' that without relying on the relevant modules ? (sort of) clone the source node and unset nid ?
Comment #38
moshe weitzman commentedlatest clone.module does what yched describes: http://drupal.org/node/110294. one tricky bit is attachments and filefield/imagefield fields.
Comment #39
yched commentedMoshe : thanks for the hint. Do you have any idea if the recent changes in files management would maybe alleviate the files / upload issues in D6 ?
Comment #40
gábor hojtsyDries, unless we have standalone objects for fields, files, whatever you want to share (nearly any node property), we can only do 'update all translation nodes on update', so when you save a node, we copy the values all around the other nodes. That is still only possible with the contrib modules doing most of the work (ie. in hook_nodeapi(update)).
That is possible to hack into Drupal core for Drupal 6 certainly, by picking some node fields to support sharing (author, update time, taxonomy terms, files, comments, poll results, menu placement, URL aliases, node flags, etc are all possible targets to share just in core). One possibility would be to relate files, comments, and so on to node sets and not nodes, so several nodes can share the same related objects. But you voted down having a separate translation set concept and asked to have the translation fields directly tied to nodes for simplicity. Anyway, this is possible to reverse, but then some values you might want to share are still simple string or number properties of nodes (flags, author, creation time, etc), not other objects tied to the node (as with files for example).
I am not sure we can have a simple solution without getting more CCK into core to have more liberated fields and properties for nodes, which we can reference and thus share a single object (database record) which all nodes point to. (I am not sure that having the above closely node-tied properties as standalone objects worth the gain by the way).
Maybe you have some ideas or brain dump to share?
Comment #41
jose reyero commentedAbout linking other content like files, to different nodes, the only problem is the way upload module in drupal handles the files, which doesn't really allow to link one file to more than one node so that's really a different problem IMHO.
For synchronizing data accross translations, you cannot do it blindly, just copying over all the fields, and not even hardcoding it for a given content type. You need a whole set on configuration options.
Example: We have an event, linked with a location, in two language versions, English and Spanish.
Case a: It is really the same event, same location, same date. Ok, for this case it makes sense to copy field contents
Case b: They are two 'language versions' of the event, like you have a talk for English speaking people, and then another one for Spanish speaking, different places, different times.
Another example: A weight for a product
it's a numeric field so we can think it's the same for all languages. But maybe we'd like to use kilograms in Spanish, pounds in English, so we cannot just copy over the value.
The point is, synchronizing translations is not something you can just do copying over all non text fields. It's a 'higher level' decision and unless we provide a whole bunch of settings we better leave it for contrib modules for now. Because any solution we provide for all translations in general will cause more trouble than benefits for site specific implementations.
Note: I'm implementing a solution for this for i18 module/Drupal 5, and it consists on providing the whole list of fields for each content type the administrator can set as 'synchronized' or not. And the only thing that would help here is to have some _fields hook for all node types which provides human readable information on what each field means.
Comment #42
mgiffordThere is a lot of potential flexibility that you might want for Drupal 6, but I don't think we need to wait until we've got a whole new configuration mechanism to allow admins to choose what fields they want to be translated.
- there needs to be a means to have the translations behave like they did in 4.7 or 5.x (it may seem like a bug, but people may be dependent on it). This should be a simple checkbox in the config.
- we need to implement a new default for synchroniziing translated nodes. Having numeric fields be linked by default will provide a better user experience for most instances. Ideally it will be customizable for each node type. Each module should be able to define an array of linked fields that they want to be the default for multilingual data. It would be quite complicated to do this for CCK node types. The default set of tables could be patched produce a different set of linked resuts.
- Once we've got core modules using this then I think it would be a good time to add in the user interface changes so that users will be able to select which fields they want to have translated for each node type. I think that could wait till Drupal 7 though.
Comment #43
Moxide commentedUsing the latest patch :
Expected : English is marked as "Translated"
Issue : English is marked as "Not translated", so it's possible to translate the English page into English.
If you translate the English page into French or German, and click "Translate" tab, information are correct : English is marked as "Translated" and "source", French or German is marked as "Translated".
Another small issue :
Expected : German language is not listed
Issue : German is listed, and clicking "Add a translation" opens a page creation form, its language being set to "Language neutral".
Comment #44
gábor hojtsyDries reviewed the module in person with me, and asked me to get back with a better version. Here it is. Changes include
- .info file needed to be updated with core compatibility information
- removed done todos from the top, added overview docs
- added help for node translation tab
- unified content type translation support checking into translation_supported_type()
- renamed 'snid' to 'tnid' and 'tr_status' to 'translate', as well as $trnode in the code to $translation_node
- added expanded description to content type setup page
- removed 'language neutral' option when editing a node in a translation set
- updated the overview page to reflect the start of a translation set (bug noted by Moxide)
- fixed nodeapi translation support checking
- simplified translation_node_get_translations() to only accept a $tnid, and only return a partial node object (SELECT * was used, but is inappropriate, so I included only the fields we use... proper node loading should be done with node_load() as done in this module already when needed anyway)
Updated patch attached which works with Drupal HEAD. To prove this and show how all this works without even applying the patch (although that would help you find and report nasty bugs :), I have made a short video demonstration.
Watch node translation in action (intentionally no audio, 10MB)!
Please test, review, comment! Let's get this in!
Two things that should be discussed:
- How to add existing nodes to a translation set? How easy it is to provide a node selection widget on the translation tab if we have like a few hundred nodes to choose from?
- How to remove nodes from a translation set? (This was hackisly possible before by setting the node to language neutral, but I just removed that awkward possibility - which is considered a bug). An easy answer to this would be to have a 'remove from set' link on the overview page among the operations. If I mistakenly remove a node from the set, I might as well need the previous feature.
Comment #45
yched commentedThis was already missing in my patch in #33 / #34 :
the update function does not create the indexes on tnid and translate columns
Comment #46
yched commentedAlso, now that we removed the ability set translated nodes back to 'Langage neutral', i don't think this branch in translation_nodepi('submit') is still needed :
And last for tonight : function translation_path_get_translations($path) does not seem to be called anywhere.
All these points were already valid objections to my previous patches :-/
Comment #47
davemybes commentedGabor, for the node selection option, a patch was already accepted into i18n that added an autocomplete input field above the list of available nodes. For more information, see http://drupal.org/node/137049. Jose mentioned that he did some minor changes to the patch I submitted, so you might want to double check with him exactly what changes he made.
Comment #48
gábor hojtsyyched, that "remove from translation set" code might not be used *here*, but any contrib module has the possibility to do funky things in the form, so it is better to cover this possibility IMHO.
I also noticed translation_path_get_translations() standing alone, but figured that it is supposed to be used for the language switcher block (http://drupal.org/node/141996) but until that gets committed or an API is decided there, there is no point to include the alter function here to tap into that. Well, we can as well remove the translation_path_get_translations() function if deemed better and add it back later if the language switcher block hits core and we build in better support for that here.
Indexes are missing, indeed.
Comment #49
dries commentedI had another look at this, and have a number of comments. Note that NOT all these comments need to be addressed. It's more of a brain dump, although I would expect other people to wonder exactly the same. It would be great if we could give them some additional thought.
* It seems like a good idea to remove any code that is not being used. I don't think other modules will make assumptions, or that they are not able to deal with things themselves.
* How often do you want to add or remove a node to/from a translation set? I don't have a lot of experience translation Drupal site, but this requirement never occurred to me (although I can see it being useful). Getting the UI right for this seems to be the biggest challenge.
* In the translate.module's global help text, it might be useful to drill down on the architecture a bit. I'd add a second paragraph that describes the different database fields that are relevant to content translations, and how they are being used. That sort of information seems to be a natural extension to the first paragraph.
* I'm not sure whether "one source content" is valid English.
* From a user point of view, the UIs seem to make sense. The one thing that might be confusing is the word "translation set" and "source node". Both sound rather techie to me. I think non-technical people would simply refer to it as "translations" (instead of "translation set") and "the original post" (instead of "source node"). I think we need to think about this some more. First, "Translations" might be the better word, especially in the UI. Second, I wonder why the user should care about there being a "source node" to begin with.
(I can foresee a scenario where there is an English source node that is translated to Hungarian, and where the Hungarian translator might decide to mark the source node as "outdated". At that point, the notion of there being a "source node" is rather moot. At least from the user's point of view.)
To make a long story short -- we might be able to take this one step further and eliminate two slightly technical terms.
* The UI leaves me with a couple of question though: what happens when I delete the source node? Will the translations be deleted too? This is something that we'll want to document because I can't predict the behavior. The fact that there is a source node suggests that the translations will be deleted too. If there is no longer a source node, I would not know what to expect.
* The UI leaves me with another question. On the node edit page you can mark translations as outdated. The form description reads "Mark all the content of the translations as outdated". My question is simple: what does it mean for a node to be marked as outdated? Does that mean that the node will no longer be accessible? To me, it means as much as "flag this node". There are two things missing from this description: the purpose and the effects? Why is this useful? What will this cause to happen? Both are undefined.
* Feature request: if would be great if we could integrate the translations module with the forthcoming actions module. Like that, we create more interesting workflows (i.e. send an e-mail to the Hungarian translation team). This might be a good opportunity to review and evaluate the actions patch.
* Is there an easy way to see all outdated translations? How does a translator identify all the missing or outdated translations that he/she has to work on? I realize that this can be solved by a contributed module, but maybe it is as simple as adding something to the filtering operations on the node administration page. Not sure but maybe worth thinking about. Maybe this requires further integration with the node.module (and the status field) to get this 100% right?
* For mere mortals, the difference between "locale" and "translations" might be a little hard. The administration page shows "locale" and "content translation". I wonder if we can make this better. I know we talked about this before, but it something that keeps bugging me. I don't have a definite answer and I don't expect one either. Just dumping my raw thoughts.
Comment #50
gábor hojtsy1. Code remove: sure, removed the small piece pointed out by yched. Made use of the path lookup function though with an implementation of hook_alter_translation_link() to provide a feel of how the language selector block would interact with translated nodes, in anticipation that that patch (http://drupal.org/node/141996) will get in.
2. Removing and adding nodes is indeed not an everyday operation. You would mostly need them when you migrate content from somewhere else. Like if you post with blogger API or Atom Publishing API and would like to put the translation in place into the set. I am fine with not including support for these in core, and leaving this to contrib to not complicate matters too much for us.
3. Added the table field descriptions.
4. Terminology stuff. The source post is used to be able to track "updatedness" across the board. If you see your translation is outdated, you will check the source post for new stuff. The "add new translation" links does lead you to a form prefilled with the actual content you have been viewing, not the source post content, that might be misleading, and could be corrected.
The concept is that source posts are "more equal" then others, they are the reference point in your translation. This is good for updated status checking of translations and is also good for shared field implementations in contrib. There is a canonical value to look at that way. If you would be able to update a translation and mark other nodes in the set as outdated, we would need to store what node made the others outdated, so the translators can check that. That would also imply that the translators know any of the languages, so they can sync with changes in any of them.
Maybe it is also a conceptual enforcement if we only allow translations of the source post (prefill the form values always with content from the source post when starting a new translation). That implies that translators all know one common language in the translation set, the language in which the source content was written. We does not enforce this yet (you can prefill with any existing node content you want), but if that would clean up the source vs translation relations, I am for it.
5. Source node deletion: I don't think we would like to see all translations removed at once. Well, how can we communicate this better?
6. Flag as outdated: I have updated the labels and help texts there, hopefully it is cleaner now. Unfortunately we don't know what *will* happen, maybe an action will fire if the user set it up, so the post could be unpublished or the translators can be notified or anything. Anyway, I have included a help text, which indicates that only the flag will be set, other properties of posts will not change.
7. Actions: I am sure you have seen my extensive actions review ;) What do you think, how actions could be useful here? What action would you like to see? "Send an email to someone when some translation is marked as outdated" seems to be logical, with "someone" and "some translation" == "language" being configurable.
8. Overview: added quick status options to the node filtering screen
9. "Locale" and "content translation": I bet you mean the module list?! Otherwise these do not display anywhere... There is no such menu item or page titled "content translation". Well, we can name the locale module "interface translation" there in the module list, if that would not confuse people. I think it could easily confuse them.
Comment #51
dries commentedThanks for the explanation. That helped clarify various things -- especially regarding the 'source node'. New users might still have the same questions as I have, so it is worth communicating the essence of this to the user. You explained it to me, but you might also want to explain it to the user. ;) It's the kind of information that helps the user wrap his head around this. In the help text, explain in 2 or 3 sentences what a "source node" is and how that concept is useful for the user.
Source node deletion: I don't think we would like to see all translations removed at once. Well, how can we communicate this better?
I'm not advocating that we'd delete all the translations. I just think that we need to be explicit about this. Print something like: "This post has x translations. Deleting this post, will not delete the translations.". And then maybe another sentence to explain the implications (if any).
That still leaves me with some questions, but these are certainly less important. One example question: does that mean there will be a new source node that I can use to /fork/ new translation from? What are the implications of orphaning translations. Does that break the integrity of my data?
Flag as outdated: I have updated the labels and help texts there, hopefully it is cleaner now. Unfortunately we don't know what *will* happen, maybe an action will fire if the user set it up, so the post could be unpublished or the translators can be notified or anything. Anyway, I have included a help text, which indicates that only the flag will be set, other properties of posts will not change.
Interesting but still somewhat confusing. I think this part of the patch is somewhat under-developed. There a handful of things that _could_ happen when the source node is updated: we could just flag the translations and wait for translation teams to pick it up, we could flag the translations and unpublish them, we could optionally e-mail the translators, etc. As a user, even as an administrator, you don't really know what is going to happen and you don't have control over it either. Try to put yourself in the position of a user that does not know how translations work.
* I might want to trigger different combinations of these events depending on how important that node is.
* If I don't know what is going to happen, I'm not likely to check that box. I'm going to search for a good explanation first.
So two problems here: (i) lack of control and (ii) not clear what is happening under the hood. I'm not convinced this checkbox is the proper solution. It just adds an extra level of indirection, it seems.
I'm not saying that we need to fix these now. It's not a show-stopper, but it is certainly something where the modules comes short, IMO.
"Locale" and "content translation": I bet you mean the module list?! Otherwise these do not display anywhere... There is no such menu item or page titled "content translation". Well, we can name the locale module "interface translation" there in the module list, if that would not confuse people. I think it could easily confuse them.
Yep, I was talking about the module configuration screen.
Comment #52
gábor hojtsyDries, I think the source node and the workflow options you describe relate close to each other. Now the source node offers a starting point for the workflow. The question is who should implement the workflow. Now that actions module is getting into core, I don't think we should explicitly include stuff like 'send email to translators when translation is outdated' and so on. I don't think it belongs into this UI or if it does, it does not belong to translation module implementation-wise.
Seems like we already agreed that the field sharing workflow will be supported in contrib modules. The simple 'mark as outdated' "workflow" was added on your request, and it is just that, simple. Other modules do a lot more in proper workflow support, and actions is a big part of that. Sure user module and other modules have their own "actions setup" screens (think user notifications), but now that we are moving actions into core, I am not sure we should expand on this type of custom actions implementation practice here.
I wholeheartedly agree that people will want more then what this module offers, and that the 'mark as outdated' option is a very bare-bones function right now. I think other modules should attach behavior on it (it is done in nodeapi update, so other modules can intercept it!). We can axe this out and leave this completely to contributed modules, where a more complete workflow can be implemented. That would also mean that the source node concept becomes meaningless in core, as we would not have any special meaning for a source node, and we would only have straight and simple translation sets, leaving other features to extensions.
Comment #53
dries commentedI agree that we can add these through contrib modules or incremental improvements. As I said, it's not a show-stopper. Feel free to commit this. :)
Comment #54
gábor hojtsyAll right then. Reading through the comments here, it seems like we have two remaining problems with this patch:
- code to interact with the language switcher block patch is included, but there is no definite decision yet about that
- we need indexes added on the new fields... yched you think single column indexes on tnid and translate would be fine? I see tnid is queries in many WHERE's on its own, but 'translate' is not queried as it seems... I am not sure we need that index.
One that seems to be related but not an issue with this patch:
- Moxide noted that it is possible to disable/delete a language on the language admin interface even if we have nodes in that language... That is a flaw of the node language feature... Node should form_alter() into the language form and disable languages for which nodes exist and add a message to the page that it is the case. That is not a problem of node translation, it would be nice to submit as a separate patch against the 'language system', so we can track and solve it.
Comment #55
yched commentedwe need indexes added on the new fields... yched you think single column indexes on tnid and translate would be fine? I see tnid is queries in many WHERE's on its own, but 'translate' is not queried as it seems... I am not sure we need that index.
Yep, single column indexes should be fine.
The 'translate' column is used in an ORDER BY in translation_remove_from_set (pick the new 'source node' for tha translation set), and in a WHERE in the queries generated by the 'up to date / outdated' filter on admin/content/node overview.
So, well, I kept an index on 'translate' for now.
Updated patch takes care of defining the indexes in node.schema and adding them in system_update.
I also went ahead and removed the 'language switcher'-related translation_path_get_translations() for now.
I think we should commit this without cruft if it's ready, and then add the function back in the language switcher patch where it belongs.
Comment #56
gábor hojtsyYched... OK, fine with the indexes.
But why did not you remove translation_alter_translation_link(), which is using the path function you removed?
Comment #57
yched commentedWoops.
Attached patch removes translation_alter_translation_link() as well.
Comment #58
gábor hojtsyyched, your latest patch did not include the .info file, but I grabbed it from the 10th patch. Committed to Drupal core.
Let's work on the translation links in the language switcher block patch then (http://drupal.org/node/141996) and the language disable issue should be brought up in a new issue against the language system or node module.
Comment #59
(not verified) commented