Closed (fixed)
Project:
Content translation
Version:
7.x-2.x-dev
Component:
Code
Priority:
Normal
Category:
Task
Assigned:
Reporter:
Created:
3 Jan 2010 at 20:53 UTC
Updated:
7 Oct 2010 at 17:20 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #1
plachHere's an initial patch. Definitely needs work, just to see how the whole code looks like.
Comment #2
mcload commentedSubscribing
Comment #3
peximo commentedsubscribing.
Comment #4
Bilmar commentedsubscribing
Comment #5
jherencia commentedSubscribing.
Comment #6
mcload commentedI applied that patch and installed a fresh D7 with the patched translation module. Now, the translation page (http://localhost/d7/node/1/translate) of an article is giving the following error:
Fatal error: Cannot use string offset as an array in C:\project7\d7\sites\all\modules\translation\translation.handler.node.inc on line 24
Comment #7
plachYes, the patch still needs a heavy rework to get functional.
Comment #8
YK85 commentedsubscribing
Comment #9
Bilmar commentedsubscribing
Comment #10
YK85 commenteddoes Translation module replace Internationalization module in Drupal 7?
sorry the project page did not clearly indicate so would like to confirm
Comment #11
plachNo, the Internationalization project focuses on enabling a full multilingual workflow for site admins/builders, while Translation only replaces and enhances the core Content Translation module. Some features, e.g. content language negotiation or taxonomy translation, might overlap but most of them are unrelated.
Comment #12
plachUnfortunately there are a few issues that are blocking the initial merge:
#282191: TF #1: Allow different interface language for the same path#710526: Improve multilingual field test coverageAnd above all:
#657972: Make field fallback logic actually reusableComment #13
sunThanks for pointing to those! I'll try to help/review ASAP.
Comment #14
plachAll the main blockers got committed!
I'll try to post an updated patch ASAP. I still need a feedback on the direction taken in the first draft merge, though.
Comment #15
sunGiven that we're still changing field API and also TF functionality in core HEAD, I think it would be wise to still defer work here, until we can be a bit more sure that we don't have to chase HEAD every other day. Agreed?
Comment #16
plachI was about to start some more work on this as I think the core TF functionality is almost complete. There are some issues still pending, mostly #629252: field_attach_form() should make available all field translations on submit, #362021: field_attach_prepare_translation needs to be updated for D7 API and above all #632172: Node language and field languages may differ, but I don't think they are real blockers or "game changers".
For what the whole Field API is concerned I think we are reaching a pretty stable status, although I have to admit I didn't follow the latest developement.
Comment #17
BenK commentedSubscribing...
Comment #18
Maikel commentedsubscribing... any idea when a next patch will follow?
Comment #19
plachWell, we are all pretty busy with the release of Drupal 7 but I hope to be able to work on this soon.
If people want to speed up the work here, they may test the patches in the translation queue.
Comment #20
plachAnd finally here is a new patch!
Field translation works pretty well, the integration with node translation is still experimental and has issues (but it's there just to get a design/usability feedback) and the upgrade path is completely untested.
The node title translation issue is yet to be addressed, see #879486: Is the Title module maintained? for details.
I'm attaching the merged module also as a zip archive so testers can jump in more easily.
Comment #21
sunMy first review, checking the rough edges only, didn't really come to translation.admin.inc:
Why does a property called "human readable id" have a value that references an entity property of the entity's title? That looks odd. :)
Do I have to understand the duplicate/recursive 'translation' keys?
It looks like
1) 'edit path' could default to '!basepath/edit'
2) 'edit form' could default to TRUE. Though I'm not sure what this property means and why comment doesn't have it (because comments have an edit form, too).
It seems that this patch already contains a common/generic translation functionality for any fieldable entity, performed on dedicated menu paths provided by Translation module. I'd consider that a pretty advanced use-case already and am wondering whether we may want to defer that advanced/generic functionality to a separate follow-up issue/patch?
I already wanted to suggest 'view path' instead of 'base path' for hook_translation_info(), but now I suddenly see that base path is taken over as view path. I don't understand the difference between both.
I wonder why "overview" instead of "List"? (both in title and callback)
Also, default local tasks should always have a weight of -10; most often eliminating the need to set special weights for other tasks.
Each "task" should have a verb, not only the delete task. There are two ways, either prefix the verb (as for delete here), or append the verb (normally done if the tasks belong to something considered a fixed thing/"entity").
We should also keep in mind that we may need to add other tasks in the future.
So either
$path/translate/edit/%/%
$path/translate/delete/%/%
or
$path/translate/%/%/edit
$path/translate/%/%/delete
I wonder why there is no "add" task; suspect that there's no real difference between edit and add (yet)?
translation.admin.inc should be located in the module's root folder.
Not really sure about the entire layout chosen here. I don't think there's a need to put sub-modules into an additional "modules" sub-directory; ./translation_node/translation_node.module is just fine.
I wanted to ignore this for now, but there are quite a lot of wrongly formatted PHPDoc comments we have to fix at some point.
Should we rename this permission to "translate any entity"? Views and Panels had this very similar and security-problematic issue once.
This is odd.
Also, this seems to invoke a theme function directly, but the theme function just displays a message. So why isn't the message simply set in translation_field_attach_view_alter() already instead of a #post_render callback?
Lastly, I wonder why we are setting a message at all? When rendering 100 entities, this may potentially display 100 messages?
As already mentioned for hook_translation_info(), it seems like %id and getHumanReadableId() are not refering to an ID, but an entity's title. Why not simply %title and getTitle() ?
Didn't look at the handlers yet, but
1) "init" + "update" + "clear" sound a bit arbitrary to me. I also wonder why we need those "Translations" suffixes. "update" is the only that makes sense, although I suspect it's not that kind of "update" I am currently thinking of, as these are low-level Field API hooks. "clear" should likely be "delete". No idea what "init" means or could be.
2) Note that there's a 3rd argument TRUE in the update hook. If that's intentional, it might deserve an inline comment.
Same as above: why "get" instead of "load"? In short, I'd prefer to see usual CRUD method names here, i.e., insert(), load(), update(), delete(). Only use more elaborate method names for non-standard non-CRUD functions, such as getTitle() or similar.
It looks like we could store $info and perhaps even $handler as custom #info and #handler properties within $form.
How about expire() ?
Will there ever be more multilingual choices? If not, I think this should be a simple checkbox instead of radios.
At the very least, the internal values should be 1 and 0 instead of TRUE and FALSE, I think.
$update is normally called $reset.
Also not sure why $update (reset) is set/enabled internally if the passed $entity has no id - that's odd. :)
oh, just wanted to ask why we have a entity-specific sub-module, but yeah, this just seems to be the old Translation module 1.x.
Somehow, however, I thought we'd intermix this functionality into the new module, instead of a separate module. But that's totally not a priority right now, I guess.
Let's just use a regular form and manually invoke the upgrade. Anything else is too complex, and auto-upgrading may also not what people want. Users may mistakenly enable the module.
Should also clear entity info cache?
Odd. Do we need to open a core issue for that?
All available (including disabled) looks correct to me.
Shouldn't "class" be "handler" ?
I'm still trying to understand what's actually going on, but it looks like these methods should be renamed from "Translations" to "Language" -- they are loading, saving, and deleting values for a certain language, right?
Either way, we have to do something on those method names... all of them are called similarly, but do entirely different things. If everything else fails (though that's unlikely), then just removing the "Translation(s)" suffixes would help a lot already.
A single getPath($type) would be sufficient. Also not sure whether we need a method for that at all though.
This code confuses me :)
It looks like both methods are the same as load(), just that load() does not check whether it already loaded currently.
hum... it's very hard to review all other handler methods, since closely related methods are defined miles away from each other. Can we keep related methods together?
Powered by Dreditor.
Comment #22
Anonymous (not verified) commentedsubscribing. Happy to help test out functionality once the dev branch is 'stable' enough
Comment #23
plachA few answers while I find some time for coding.
Well, it might sound strange but almost every entity has a different field name for it (node -> title, term -> name, comment -> subject, user -> name) so I tried to find a common (and descriptive) name. If I recall well yched named node title this way for the first time in #557292-15: TF #3: Convert node title to fields. I found it an appropriate concept but we might want to find something more intuitive. Catch called it entity label in #571654-68: Revert node titles as fields.
See http://api.drupal.org/api/function/field_has_translation_handler/7 : the first level is the entity translation info (see http://drupal.org/files/issues/tf-664136-18.patch,
system.api.phphunk), the second level is the module's actual name (in this case they are the same). The original module name wasentity_translationso we had$entity_info['translation']['entity_translation'].It's rubbish, old code left there from the first patch. To be removed.
I could not manage to attach the Translation UI to comments due to differences in the admin UI path structure and workflow, so I initally thought to implement a page listing all the translatable entities not having a dedicated UI (see #539110-53: TF #4: Translatable fields UI). This indeed can be left for a later version as comments have little support for translatable fields.
'base path' is the path to which attach the Translation UI, while 'view path' is the path used to view the entity. Probably in the line above we are missing a check that the view path is unset: falling back to the base path should be only a default.
One of the guidelines while developing was to mimick as closely as possible the node translation UI. Overview is the callback name for node translation, no problems to switch to "list" for title and callback.
Ok, I'd go for the first pattern (
"$path/translate/edit/%/%"): if we'll ever need to add other tasks they might need different arguments.Exactly. I doubt there ever will be any: the translation form is available only for existing entities, and adding a translation almost only means giving additional values to the entity fields. In this scenario I think there is no great differerence between the first time and the following: we have no id or additional parameters to pass while editing translations. If we want to differentiate at all costs, while editing a translation we don't need the source language so we could have:
I followed the Field module layout for the submodules.
I have to admit I was quite proud of this (uncommon) solution :) The idea behind this is that you might want to display a warning when a translation is missing (for some reason I thought a warning message was more appropriate, yes, even 100), but you might also want to override this behavior with a properly themed content for each entity. Invoking the theming function in the #post_render call would be quite easy but at that point messages cannot be set anymore. This solution allows to support both behaviors.
This was my first solution in the core patch, it was changed after some UX discussion. Obviously no problems to revert back to a checkbox (see the last proposed UI: #563998-20: Field UI: no way to set the translatable property).
We are not resetting static cache here, just updating a value in the cached entry.
That line needs a comment: I guess (!) the reason is that if the entity id is empty, we are creating a new entity and we need to update the static cache for the null key. This is pretty weird and needs some testing.
I think we can make an inital release that simply lets the user choose between entity translation and node translation: keeping the module almost intact allows to easly apply core patches and keep it in sync with the core version. Once we find a way to make the two approaches cohexist more tightly we can merge the modules (we'll need a solid upgrade path then). Hopefully at that point the translation core queue will be (almost) empty.
Ok
I hope we won't need this as #632172: Node language and field languages may differ should address the issue. But I ain't sure about content created before enabling Locale: this needs some testing.
Yes, there are some related issues in the core translation queue that need to be considered while dealing with this, see #778528: Define the language switcher's correct behavior and #343164: Show only enabled languages on the "translations of ..." page.
They are (currently) needed in translation.admin.inc. Explictly hardcoding the path type in the method name allows a more granular overriding for subclasses.
Translation handler class
The translation handler has been designed as a wrapper for the
$entityobject: it has methods that return the object properties needed by the translation workflow. The values returned by these methods can be overridden by subclasses to fit any needed custom behavior/value (see the node translation handler). The translation handler has the role to load the translation (meta)data into the wrapped entities: translation (meta)data are retrieved from the{translation}table and are simple records that track when a translation has been performed, by who and its status.Most translation handler methods act only the translations data structure and do not involve db queries, only load() and save() methods do this.
The "Translations" suffix is needed as the operations target is the translation data structure not the handler (
$handler->init()would be totally misleading), AAMOF many methods don't have the suffix as they target the wrapped entity and not its translations field. We might want to add the "Translation" field to the "load" and "save" methods.It's a best-practice in OOP to use getter/setter methods wrapping object properties (subclasses may override them).
"load()" should be the method that actually retrieves the data from the DB (if necessary/possible), while "getTranslation" should be the one dealing with the stored data structure.
Comment #24
plachHere is a new patch. It should implement most of #21. The rest is explained in #23.
Comment #25
plachThere were some trailing whitespaces around.
Comment #26
plachBtw, I opened #896570: Add db caching to path_get_admin_paths() while working on this.
Comment #27
klonossubscribing...
Comment #28
das-peter commentedsubscribing...
Comment #29
das-peter commentedJust started to use the new interface.
I made some small changes to the current patch get it working without warnings.
Changes I made:
translation.module
Removed [entity keys][label] definitions in
translation_translation_info().Usually hook_entity_info has this already set - by using array_merge_recursive() in translation_entity_info_alter the duplicated definition led to an array in [entity keys][label].
translation.admin.inc
In
translation_overview()the variable$pathwas used for different purposes - what led to misleading links. I changed one to$translatePath.includes/translation.handler.inc
Changed method
getLabel()to use the core function entity_label() for loading the label.Currently there are other issues / questions I'm working on:
What about committing the current state into the CVS? Would make future changes more traceable.
Comment #30
plach@das-peter:
I'll have a look to the latest changes ASAP.
I'm working on a solution for titles in http://drupal.org/project/title.
We need at least one more review from sun before committing this.
Comment #31
sunI'm totally sorry -- wasn't able to spare some time to review + test this patch once more. Please note that http://drupal.org/node/363367 states
If you feel comfortable with the possibility of potentially doing major changes after the initial commit, then I'd say we should simply move on. After all, the current patch/code went through at least some reviews already (including the core TF UI issue).
Not sure whether we already created the DRUPAL-7--1 branch to hold the identical code as Translation module in core (which will allow us to compare core's code to our last known code), but in any case, we should ensure that HEAD contains the most recent code of the core Translation module (and branch that into DRUPAL-7--1 afterwards) before turning HEAD into 2.x (this patch).
Thanks for your hard work on this, plach!
EDIT: Let's do @das-peter's changes in a follow-up issue/patch.
Comment #32
plach@sun:
Nevermind, your time is well spent elsewhere :)
[EDIT]
No problem with major changes as long as they make sense ;)
[/EDIT]
I'll do this as soon as I can.
@das-peter:
Yes, please, wait for this to be committed (tonight or tomorrow at the latest) and open a new issue with a patch holding just your changes from #29 so that I can review them more easily.
Comment #33
das-peter commentedThank you both for the fast feedback.
I'm on standby and create the patch, as soon as the repo is up to date. :)
Comment #34
plachHere is a reroll of #25 synced with the latest D7 HEAD. Attached you can find the diff between the core Translation module and the Translation Node submodule shipped in #25.
Comment #35
plachPerformed some basic testing and fixed a couple of issues coming from the previous reroll.
Committed the attached patch to HEAD!
Comment #36
sunAwesome! Thank you, plach!
Comment #37
das-peter commentedThat's great - thanks!
Follow up issue created here: #920826: Several fixes after the initial merge