off-shot from #1184944-36: Make entities classed objects, introduce CRUD support to define how translated properties are handled for entities.
related issue targeted for D7 #1260640: Improve field language API DX

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

fago’s picture

The patch in #1184944-35: Make entities classed objects, introduce CRUD support already includes an EntityInterface with get() and set() methods, for which we need to define a sensible language default. I guess we need a method language() respective to the planned entity_language() to get the language the entity has been created in for that?

Also, we need some info about the entity-properties (-> entity-property-api) to know which properties are translatable. (Misses issue, I'll create on asap). For now it's probably fine if the implementation just covers fields.

klausi’s picture

fago’s picture

thanks, fixed that.

yched’s picture

Subscribe

plach’s picture

Issue tags: +D8MI

tagging

plach’s picture

Assigned: Unassigned » plach

on this one

Gábor Hojtsy’s picture

Issue tags: +montreal

My short feedback on this: language should be a mandatory piece of property on an entity. Period. Each entity should be able to tell its language. If its "language neutral", so be it, but it should be able to tell that to us, and let the user enter that metadata. If Drupal 8 is to become a fully multilingual system, there is no way to avoid this. This would mean that we'd move language information support from the node, comment, etc. module level to the general entity level.

(Note that user entities do have a language property right now which *is not* their entity language, it is the user's preferred language. Probably we should rename that, and use the language property consistently there to signify the language of the information the user provided, not the language the user wants to see on the site).

plach’s picture

Status: Active » Needs review
FileSize
6.25 KB

Here is my first attempt to address this: the implemented logic is more or less the same than the one in #1260640: Improve field language API DX. There is a compatibility layer to support language-unaware properties but I think this should be removed in favor of always accessing properties through accessor methods and defining properties as private or protected when possible.

As mentioned in #1 only field language is covered for now.

Feedback welcome :)

Status: Needs review » Needs work

The last submitted patch, entity-1277776-8.patch, failed testing.

plach’s picture

plach’s picture

FileSize
375.34 KB

Here is an updated version for the testbot including the patches above. Please review #8.

klausi’s picture

Status: Needs review » Needs work
+++ b/modules/entity/entity.module
@@ -424,6 +424,34 @@ function entity_label($entity_type, $entity) {
+ * @param $entity_type
+ *   The entity type; e.g., 'node' or 'user'.
+ * @param $entity
+ *   The entity for which to generate the label.
+ *
+ * @return
+ *   The entity language code, or LANGUAGE_NONE if not found.
+ */
+function entity_language($entity_type, $entity) {

stop passing around the entity_type, this is a method every entity object must have. Type hinting with EntityInterface on $entity would be good.

+++ b/modules/entity/entity.module
@@ -424,6 +424,34 @@ function entity_label($entity_type, $entity) {
+
+  return $label;
+}

label? should be $langcode, right?

Gábor Hojtsy’s picture

Hm, in fact language handling is also happening in #1260640: Improve field language API DX. Is there a sizable overlap between the two issues or how do they relate? If the D7 issue adds much more of a language support on the entity API, should we just take that forward here?

plach’s picture

Status: Needs work » Needs review
FileSize
375.37 KB
6.28 KB

@klausi:

stop passing around the entity_type, this is a method every entity object must have. Type hinting with EntityInterface on $entity would be good.

I think entity_language() could be dropped altogether and just moved to the Entity class. This would avoid the need of having language or language callback entity info keys, since we could provide a base implementation accessing a (protected) defined property and for any other need the method could be overriden. However here I tried to maintain consistency with entity_label(). I think we should move this discussion to #1184944: Make entities classed objects, introduce CRUD support and revisit it here afterwards.

Fixed the entity_language() function.

@Gabor:

Hm, in fact language handling is also happening in #1260640: Improve field language API DX. Is there a sizable overlap between the two issues or how do they relate? If the D7 issue adds much more of a language support on the entity API, should we just take that forward here?

Well, both are introducing the same entity_language() function atm (not sure in the future). Accessor methods are replacing accessor functions but the implemented logic is the same. We are missing something equivalent to the field_process_translation() function, but that is something that we should revisit once the Field API is moved to a real OOP implementation.

Attaching two patches: again, review the tiny one, the big one is for the bot.

catch’s picture

Copying from the CRUD thread:

For language, could we do something like $entity->setPreferredLanguage($langcode); rather than passing an argument to get()? that would mean you only have to set things once then you can just access properties as usual, and if you don't set it you get the default. It'd also feels a bit easier to move that to depending on context later on.

This would mean we don't have to implement getters for fields and properties, and ought to make things more compatible with the $context object once that's in place (i.e. eventually entity language could default to the content language in context).

gdd’s picture

+1 to catch's idea here, it seems very clean and easier to adjust later as we need to (also subscribe)

plach’s picture

This would mean we don't have to implement getters for fields and properties, and ought to make things more compatible with the $context object once that's in place (i.e. eventually entity language could default to the content language in context).

I missed this one on the other issue: how would this default language be used without getters/setters?

catch’s picture

It'd work with either __get() or get() or __call(), as opposed to only get() or _call(). I guess __get() is still a getter but that's what I meant ;)

fago’s picture

I've thought about doing something like the proposed $entity->setPreferredLanguage($langcode); too. However, this introduces some magic state to $entity. Considered we have shared $entity instances this might lead to odd bugs if someone calls functions that somewhere trigger code who is changing the language. Thus, I don't think it's a good way to go as we'd have to be very careful with that and restore the original language after each usage (ouch).

Still, we could populate $entity->$property with a reference on the property in a fixed language, while the real property values internally live in a big $entity->properties array or so.

This would mean we don't have to implement getters for fields and properties, and ought to make things more compatible with the $context object once that's in place (i.e. eventually entity language could default to the content language in context).

As discussed in #1260640-16: Improve field language API DX I also think the API should give predictable results which do not vary from page to page request, thus $entity->$property should be predictable too. Code that doesn't deal with languages won't expect that entity properties change dependent on page requests either.
As a consequence a good default language for getters, setters or $entity->property would be the entity's (default) language. Still, the entity-display system should default to the context content language, i.e. entity->view() as well as possible methods to render certain properties.

My short feedback on this: language should be a mandatory piece of property on an entity. Period. Each entity should be able to tell its language. If its "language neutral", so be it, but it should be able to tell that to us, and let the user enter that metadata. If Drupal 8 is to become a fully multilingual system, there is no way to avoid this. This would mean that we'd move language information support from the node, comment, etc. module level to the general entity level.

Sounds good, but can we clearly specify and document what the entity language actually means? Some thoughts:

* The entity language is basically the *default* entity language, i.e. callers can expect each translatable property to have a value in that language, or there is no property value. Translations to other languages might exist, but need not.
* Does an entity language of LANGUAGE_NONE mean translatable properties cannot be translated? Is this even a valid combination?
* How do I know which translations are available? Do translations have to be complete, i.e. have translations for all properties that are set in the entity default language?
* What happens to the translations once we set a new property value using the entity language? Are the automatically cleared?

fago’s picture

Talked to gabor on IRC to clarify some of the questions:
Summary:

  • Entity language: The language the entity was created in.
  • We translate entities, not property values. Thus a property may be set in a certain translation, but needs not be set in another translation.
  • Entities with language LANGUAGE_NONE are not translatable, thus can't have translated property values.

Then there is the question on how to deal with programmatic property value updates. Should setting a new property value in a certain language, invalidate existing translations for this property?

I'd say no. As we are translating entities, not property values, it should invalidate nothing *or* the whole translation of the entity. So it might be a good idea to add an method that says "invalidateTranslations()", which removes *all* translated property values (or just marks them as outdated?)

Also, I guess we'll need a way to determine the languages of an entity, for which translations exist.

plach’s picture

I'd say no. As we are translating entities, not property values, it should invalidate nothing *or* the whole translation of the entity. So it might be a good idea to add an method that says "invalidateTranslations()", which removes *all* translated property values (or just marks them as outdated?)

We have built-in support for this in the core translation module: while editing a node translation, the user has the possibility to mark all the other ones as outdated. Entity translation extends this behavior to every entity. At the moment it's implemented as a method setting an internal property for each available translation.

Honestly I won't totally throw away the idea of marking each property as outdated, since it would make far easier for the translator to locate the part pf the translation that needs to be updated. Combine that with revisions and diff support and you get a very complete tool :)

Gábor Hojtsy’s picture

Yes, I agree it should mark them translated, not remove them. Users would be horrified for their careful translations being removed. Also agreed that marking the whole thing outdated combined with revisions and diff module should give you a powerful tool, not sure we need property/entity level flags since that would necessitate a checkbox on each of them, because we rely on the user to say it was a substantial change or not. Think a typo fix in the English text will not necessitate a translation update, but a new paragraph added probably will.

plach’s picture

Not sure we need property/entity level flags since that would necessitate a checkbox on each of them

I was thinking about keeping track of every field/property change internally as a support for the diff tool, but this is sci-fi compared to the problems we have to face now :)

fago’s picture

Think a typo fix in the English text will not necessitate a translation update, but a new paragraph added probably will.

Yes, but also I might not care even if I added a paragraph. :)

Not sure we need property/entity level flags since that would necessitate a checkbox on each of them

Having property level flags sounds odd. I'd prefer to avoid any extra weight in form of additional flags if possible.

Yes, I agree it should mark them translated, not remove them.

The question is probably how you want to deal with "outdated" translations. Should they still appear if the content is listed? That's probably use-case dependent.

My naive approach would be to use revisions in that case and only included up2date translations in a revision. So when I get the latest revision of an entity, I can be sure that only up2date values are in there. That's useful on the API level as you wouldn't have to care about dealing with out-dated data. Then, when looking at the translation history there is a clear relation between a translation and its source text as it is always stored in the same revision.
That way, we could support doing a new revision outdating existing translations (=removing them), doing a new revision keeping translations and a "minor change" maybe not creating a revision at all.
Does that make sense?

Also, I guess we'll need a way to determine the languages of an entity, for which translations exist.

Questionable how this should be implemented. With the current approach we'd have to loop over all properties to determine whether there is a value for a given language? Ouch.

So what about using the following approach for *internally* storing properties in an entity object:

$entity->language = LANGUAGE_NONE;
// Translatable property:
$entity->title = 'Foo';
// Not translatable property:
$entity->status = TRUE;

$entity->language = 'it';
// Not translatable property:
$entity->status = TRUE;
// Translatable property in entity language (it):
$entity->title = 'Foo';
// Translatable property translation (de):
$entity->_translations['de']['title'] = 'bar';

-> That would make it easier to handle translations I think, as all values associated with a certain language are stored in a language specific array. Moreover, entity objects look simple and always look the same way even if they are language specific. The location of a property value would be the same regardless whether the property is translatable or not - that's not the case currently in d7 and causes pain even if you don't use translations (see d7 issue). Then, only once translations are added the according $entity->_translations array is populated.

Note: There are still the getters/setters for easy access to translated values.
Thoughts?

yched’s picture

Re: end of #24 :
We considered something similar back when discussing the data structure for translatable fields - a kind of switch that substitutes the field values in a given language, putting one single language forward while the collection of values for all languages are kept in a "less visible" bucket.

IIRC, we punted with that approach, not feeling really comfortable with the conceptual impact of introducing a notion of "state", which afaik is completely absent in our current APIs and DX concepts, and is not a minor change - an $entity is not "just the same $entity throughout its load / display / modify / save cycle" anymore.

Not to say that such an approach shouldn't be considered again, just saying there is a conceptual shift I personally don't fully measure. We should probably dig for that previous discussion in the original TF d7 thread.

Gábor Hojtsy’s picture

I personally don't think we should complicate our life with this state concept, contrib modules can provide that by overriding the displays. IMHO we should skip this and focus on our core goals.

fago’s picture

IIRC, we punted with that approach, not feeling really comfortable with the conceptual impact of introducing a notion of "state", which afaik is completely absent in our current APIs and DX concepts, and is not a minor change - an $entity is not "just the same $entity throughout its load / display / modify / save cycle" anymore.

Agreed - I've thought about that too and I agree it's a bad idea - $entity has to always look the same way and should not contain any state. The approach of #24 would just re-arrange how translated values are stored though, but not introduce any state.

Well, while #24 would be nice for the case of solving "which languages" exist I'm sure there are there other disadvantages, e.g. it would make copying a property including its translations to another entity harder.

IMHO we should skip this and focus on our core goals.

ok. Let's skip that internals for now and focus on the interface developers make use of.

So what about that part of #24?

The question is probably how you want to deal with "outdated" translations. Should they still appear if the content is listed? That's probably use-case dependent.

My naive approach would be to use revisions in that case and only included up2date translations in a revision. So when I get the latest revision of an entity, I can be sure that only up2date values are in there. That's useful on the API level as you wouldn't have to care about dealing with out-dated data. Then, when looking at the translation history there is a clear relation between a translation and its source text as it is always stored in the same revision.
That way, we could support doing a new revision outdating existing translations (=removing them), doing a new revision keeping translations and a "minor change" maybe not creating a revision at all.
Does that make sense?

fago’s picture

FileSize
5.75 KB

ok, I re-worked the patch based upon the discussions. Please review.

Once we've a basic agreement, I guess we should do same basic test cases for that functions, i.e. make the test-entity translatable, add some translatable fields + values + test methods.

Note: The patch is based upon #1184944-113: Make entities classed objects, introduce CRUD support, so it won't apply.

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

The last submitted patch, drupal_entity_lang.patch, failed testing.

Gábor Hojtsy’s picture

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

#28: drupal_entity_lang.patch queued for re-testing.

Gábor Hojtsy’s picture

I think this generally looks good except langauge_load() unfortunately is located in locale.module, so you cannot just use it as you did. We can move that too to bootstrap.inc, and so some similar logic like in langauge_list() to work when we have no locale, and just work with the default language in that case. Not sure we should do the move of language_load() here, but I see this patch demonstrates a good reason to do move it to a common place. (Making language.module required for sites did fall short of getting any support elsewhere).

Status: Needs review » Needs work

The last submitted patch, drupal_entity_lang.patch, failed testing.

fago’s picture

Status: Needs work » Needs review

I see. How should we handle an entity of a certain language once the locale module has been disabled? Treat it as language neutral? Makes sense to me, however it would mean we'd loose all property values then... That could be fixed though, e.g. by moving to an internal object structure as proposed in #24.

Gábor Hojtsy’s picture

Yeah, well, Drupal 8 now provides specific hooks for when languages are removed, so entities can react to that in ways. See http://api.drupal.org/api/drupal/core--modules--node--node.module/functi... for example for the node module that nulls out node language info for removed languages, that might or might not in fact be good for fields, but its the same behavior like in D7, just we have a dedicated hook to do it. In D7 it was directly in http://api.drupal.org/api/drupal/modules--locale--locale.admin.inc/funct..., woooooaaahh, yeah.

There are no hooks to prevent languages from being removed, if we'd rather add that, and require user to clean up their stuff first, we can do that too. All-in-all I think it is best to handle the possibility we have a language that is not language_load()-able.

fago’s picture

Status: Needs work » Needs review
FileSize
5.02 KB

Interesting :) So if there would be a possible problem with going-away property values, it would be already in d7 :D Thus, handling the entity as neutral then should be fine.

Updated patch attached. Based upon #1184944-116: Make entities classed objects, introduce CRUD support.

Status: Needs review » Needs work

The last submitted patch, drupal_entity_lang.patch, failed testing.

fago’s picture

Gábor Hojtsy’s picture

Status: Needs review » Needs work

Needs a reroll now that classes entities landed.

sun’s picture

Issue tags: +Entity system
aspilicious’s picture

Status: Needs work » Needs review
FileSize
5.13 KB

:)

fago’s picture

#40: 1277776-language-handling-40.patch queued for re-testing.

Gábor Hojtsy’s picture

Issue tags: +language-content

Tagging for the content handling leg of D8MI.

Gábor Hojtsy’s picture

I've just submitted "Drupal 8 entity property translation BoF" for Drupalcon Denver. If you are going to be there, please comment there so we can figure out the best time to do it.: http://denver2012.drupal.org/forum/drupal-8-entity-property-translation-bof Thanks!

Can someone summarize the outstanding questions here? I have a hard time following what are the exact goals and where are we against those?! Thank you!

Gábor Hojtsy’s picture

Title: define language handling for entities » Add field/property get/set to entities with language support
Issue tags: +sprint

Also likely more accurate title and an attempt to elevate the discussion by bringing to focus :)

plach’s picture

I tried to sum up the issues to be covered in http://groups.drupal.org/node/197848#api-dx and following.

Gábor Hojtsy’s picture

I don't think we want to solve all that here, do we?

fago’s picture

#40 looks good to go for me. So please review.

@plach: From the g.d.o. post:

if the entity component data is going to be read/written in a view (read) context, then we need to default to the current content language;
if the entity component data is going to be read/written in a form submit (write) context, then the correct default should be the form language, i.e. the language of entity variant being created/edited.

I'd disagree with the former. Moreover I think that this behavior is the cause for the pain in D7 right now, see #1260640: Improve field language API DX. Getting an entity value must be reproduce-able over page requests, thus the same regardless from the user being logged in.
Also, obviously getting a value and writing it back should work. Thus, imo getters/setters should always default to the entity language. That way it also doesn't matter much if an entity is translatable, the default getter/setters stay the same. You are always dealing with the entity's "default values", regardless whether they are language neutral or in a certain language.

However, I could see a getTranslation() or so useful which defaults to the current display language. Still, the regular getter should not involve any magic.
FYI: I'm about to add such a method to the d7 entity api module, see #1356978: add basic i18n support.

Gábor Hojtsy’s picture

Status: Needs review » Needs work
+++ b/core/modules/entity/entity.class.incundefined
@@ -245,6 +299,86 @@
+    if (module_exists('locale') && isset($this->langcode)) {
+      return language_load($this->langcode);
+    }

Drupal 8 has language module which handles languages now. The field language system is still in some level placed in locale module, but we are clearing that out for UI translation stuff only, so maybe add a @todo to move to language.module later.

Also, the progress on making all entities use langcode instead of language as property is going much slower then expected. #1410096: Convert comment language code schema to langcode might land soon, but we still have outstanding issues for users and (#1439680: Rename $user language property to langcode) nodes (#1439686: Rename $node language property to langcode). (We also have an issue for fields, but that does not apply to this patch: #1439692: Rename field language properties to langcode).

So if we want to have this land soon, we'd need to add a backwards compatibility layer, so it checks for ->language and ->langcode as well. Both should not be there at the same time. (Also with a @todo). Looks like this is the only place this is being checked so the damage is limited. I think that would look a bit ugly but don't have better ideas to get this moving sooner.

Otherwise looks good IMHO.

yched’s picture

+++ b/core/modules/entity/entity.class.incundefined
@@ -245,6 +299,86 @@
+      $field = field_info_field($property_name);
+      $default_language = $this->language();
+      if ($default_language && field_is_translatable($this->entity_type, $field)) {
+        $langcode = isset($langcode) ? $langcode : $default_language->language;
+      }
+      else {
+        // Non-translatable fields always use LANGUAGE_NONE as language code.
+        $langcode = LANGUAGE_NONE;
+      }

That snippet is completely duplicated between get() and set().
Could this be factored out to a protected helper method ? like $langcode = $this->resolveLangcode($property_name, $langcode); ?

13 days to next Drupal core point release.

yched’s picture

+++ b/core/modules/entity/entity.class.incundefined
@@ -245,6 +299,86 @@
+    if ($default_language = $this->language()) {
...
+        $langcode = isset($langcode) ? $langcode : $default_language->language;

Shouldn't this be $default_language->langcode ?

13 days to next Drupal core point release.

fago’s picture

Drupal 8 has language module which handles languages now. The field language system is still in some level placed in locale module, but we are clearing that out for UI translation stuff only, so maybe add a @todo to move to language.module later.

ok, added that.

So if we want to have this land soon, we'd need to add a backwards compatibility layer, so it checks for ->language and ->langcode as well. Both should not be there at the same time. (Also with a @todo). Looks like this is the only place this is being checked so the damage is limited. I think that would look a bit ugly but don't have better ideas to get this moving sooner.

I don't think we need BC here, as we can just fix it in the entity type's language() class. I've done so for comments - what we can remove once the comment-langcode fix goes in.

That snippet is completely duplicated between get() and set().
Could this be factored out to a protected helper method ? like $langcode = $this->resolveLangcode($property_name, $langcode); ?

Agreed. However, it's field-API specific so I've moved it to $this->getFieldLangcode() for now. In the long way I'd prefer field-API specific language handling to go way, but have a common, unique way for language handling for all entity properties, including fields.

Shouldn't this be $default_language->langcode ?

Yep, also there were quite some other issues. I've added tests for the introduced methods + fixed all problems I ran over. Please review.

Related, I've added a $langcode property by default so it makes sense to assume it's there in language(). I think it's safe to add this by default, as it's fine for entities not being translatable too. It defaults to LANGUAGE_NONE anyway.

Further thoughts:

  • I think we need something like a 'langcode' entity key too, so we can query for entities in a specific language and/or their translations. However, before we repeatedly enlarge the kind of deprecated 'entity keys' (we have methods now!) I think it makes sense to introduce this "mapping" as part of #1346220: Add entity property metadata.
  • Right now, we don't have any language fallbacks implemented. I think we need to support at least the following two use-cases though:
    a) A translated value is requested but no translation is there, thus fall-back to the entity language.
    b) Modules want to check for not existing translations, thus skip any fallbacks and return NULL.

    Here, a) is probably the most often desired one. Then, we also have the current possibility to define custom language fallbacks of the field-API. I don't think that plays in though as those are display related, right?

Any thoughts on fallbacks of the API function? I could see it being a further parameter to the getter(), a boolean $fallback defaulting to TRUE.

fago’s picture

Assigned: plach » fago
Status: Needs work » Needs review
FileSize
13.8 KB

and the updated patch.

Gábor Hojtsy’s picture

@fago: well $comment->language to $comment->langcode looks close to land in #1410096: Convert comment language code schema to langcode. There are definitely other entities like $user and $node where the issue is not started yet (look at the "langcode" tag). There also entities so far missing langcode (taxonomy term, file, etc). The plan was/is to convert the language properties to langcode and introduce langcode in schemas where it was missing. These are happening in parallel in other issues, just wanted to double check you agree its a good plan.

I see / agree we can overcome the missing $langcode values with a LANGUAGE_NONE default and the language properties with a method override, so we don't make the commit of this patch dependent on any of the other parallel work. (I'm holding a D8MI sprint in person tomorrow in Budapest and over IRC on #drupal-i18n and will try and get people make significant progress on the langcode conversion and introduction issues).

fago’s picture

These are happening in parallel in other issues, just wanted to double check you agree its a good plan.

Yep, definitely!

I see / agree we can overcome the missing $langcode values with a LANGUAGE_NONE default and the language properties with a method override, so we don't make the commit of this patch dependent on any of the other parallel work.

Yep, that's fine imho. If the langcode-fix has gone in before an entity-type is converted to the EntityInterface, we are fine. If not, we'll just have to add the interim language() method override to the entity type class in the entity type conversion issue. Afterwards, the language-code fix issue can remove it.

fago’s picture

Shortly discussed this issue with Gabor on IRC. Outcome:

  • We'll also have to care about multi-lingual entity labels. $entity->label() needs a language parameter, which should probably default to the interface language.
  • The fallback approach of #51 makes sense.
  • Let's move on with this patch and do a language-related follow-up for fixing the above two issues.
Gábor Hojtsy’s picture

It looks good IMHO. Anybody else has concerns? :)

Crell’s picture

How will that default be handled? Not via a global check, I hope...

fago’s picture

The language default is the entity's language, thus no global checks. E.g. see:

+++ b/core/modules/entity/entity.class.inc
@@ -245,6 +306,87 @@ class Entity implements EntityInterface {
+    if (field_is_translatable($this->entityType, $field) && ($default_language = $this->language())) {
+      return isset($langcode) ? $langcode : $default_language->langcode;
+    }
plach’s picture

@Crell:

As I wrote in http://groups.drupal.org/node/197848#api-dx, I was playing with the idea of making the Entity object context-dependent by passing it an (optional?) context/request at instantiation. @fago's perplexity made me somehow reconsider this approach, which IMO has a good potential in terms of easing DX if properly handled, i.e. by always defaulting to the entity language except for specific cases, such as the editing workflow.

An alternative could be to make the default alterable by controllers, which would be responsible for providing the right context to the entity object.

fago’s picture

yep, as said I don't think we want that much magic to happen in entity objects. Entity objects represent our data, which we need to access in a reliable, context-independent way.

Still, anyone outside can implement the logic to apply any context to retrieve the right context-dependent values from an entity.

plach’s picture

@fago:

However simply defaulting to the entity language will not always work, unless people start passing the langcode parameter, which is not going to happen. Think about entity tokens, for instance. It's a good approach for D7, which ships with an half-baked entity language support, but for D8 it's far too limiting.

Crell’s picture

Well the entity object itself should not get a request object, because HTTP behavior should be utterly irrelevant to a data object. If it needs the language, which is usually tracked in a request object, then we need some intermediary code that will take the language information and set that on the data object using an agnostic API.

As long as the default language that an entity uses is something passed to it as a language string/object/struct, rather than something it has to retrieve from elsewhere or an irrelevant object that gets passed to it (eg, Http Request object), I'm OK with that.

plach’s picture

Well the entity object itself should not get a request object, because HTTP behavior should be utterly irrelevant to a data object.

This is one of the reasons why I suggested to stick with the context terminology in the "Rethinking WSCCI" thread :)

fago’s picture

As long as the default language that an entity uses is something passed to it as a language string/object/struct, rather than something it has to retrieve from elsewhere or an irrelevant object that gets passed to it (eg, Http Request object), I'm OK with that.

The default language stems from the data storage too, it's the language the data has been created in. No magic involved.

However simply defaulting to the entity language will not always work, unless people start passing the langcode parameter, which is not going to happen. Think about entity tokens, for instance. It's a good approach for D7, which ships with an half-baked entity language support, but for D8 it's far too limiting.

Usually code should pass the target language, as the token system already supports. Still, we can think about adding helpers for appearing use-cases, as getting properties in display language. As usually the display case should be handled by an "entity display" system anyway, I'm not sure we'll need such a helper. But if the need comes up, why not.

plach’s picture

Usually code should pass the target language, as the token system already supports. Still, we can think about adding helpers for appearing use-cases, as getting properties in display language.

Honestly I did not see enough code handling with ML entities yet, so I have not a solid opinion about this. I'm just afraid people will start skipping/forgetting the $langcode parameters since things work anyway without them (unless you test your code in a ML environment, obviously).

As usually the display case should be handled by an "entity display" system anyway, I'm not sure we'll need such a helper. But if the need comes up, why not.

Let's go on with this approach then, we still have time to revisit this part if need be.

Gábor Hojtsy’s picture

@plach/@fago/@Crell: the same problem will apply to CMI and people will need to pass around language information or they are going to get their fare share of bug reports :) And we need to document this proper obviously for them. I don't think this is really hard if we give proper examples.

Gábor Hojtsy’s picture

Status: Needs review » Needs work

The comment langcode change landed last week, so the above code is not correct anymore. The rest of the langcode renames / introductions at least for entities are at #1454538: Add langcode property to all entity types; for the user entity, distinguish entity language from user's language preference which is also pretty close to RTBC. Not sure if we want to help push that in this week and then get this one in right after? (Ie. hopefully before Drupalcon :)

Gábor Hojtsy’s picture

Status: Needs work » Needs review
FileSize
13.29 KB

Removed the comment part, the others still applied. Needs review! Anyone has more concerns?

yched’s picture

Hm, I'm a bit embarrassed for not coming up with this earlier, but his approach reintroduces a hard dependency on field.module within entity.module, which is something other patches that went in earlier in the cycle tried to eliminate.

Not sure of the right answer about this.

yched’s picture

A possible answer is to have field.module provide a FieldableEntity class:

Class FieldableEntity extends Entity {
  function get($property_name, $langcode = NULL) {
    If $property is a field {
      Do the field stuff 
    }
    else {
      return parent::get($property_name, $langcode);
    }
  }
  
  ...
}

Then fieldable entities extend that class rather than Entity.

Gábor Hojtsy’s picture

@yched: yes, that sound like a good compromise. I guess core entities would extend from that.

plach’s picture

Although this could be a working solution, I think Fieldable would be better suit as an interface: should a custom entity need a different class hierarchy it would be stuck with no field (and no field language) support.

Perhaps defining Field(s) as a subclass of a Property class, as @fago is proposing, would help here?

Crell’s picture

Agreed with both #70 and #72: Provide an interface, always code to the interface, but also provide a default class implementation that the 90% use case can just use.

In which case, we have a FieldableEntityInterface, a PropertyEntityInterface, and abstract classes (or maybe concrete classes) that implement one or both of those that most people will use in practice.

(In PHP 5.4, I'd say provide an interface and a trait. Something to look forward to....)

effulgentsia’s picture

If a module wants to change an entity type from not being fieldable to being fieldable, would be nice to be able to do that simply by changing 'fieldable' in hook_entity_info_alter(), not that *and* change the class. Even if we have a default class that implements only PropertyEntityInterface and not FieldableEntityInterface, is there any reason we would ever want to use that class? Also, seems like a default class that does implement FieldableEntityInterface should still be able to handle the case of field.module being disabled or 'fieldable' being set to FALSE.

So while I like the idea of a FieldableEntityInterface, I'm questioning whether field.module is the correct place to define it.

effulgentsia’s picture

Perhaps defining Field(s) as a subclass of a Property class, as @fago is proposing, would help here?

If this means decoupling the entity class from the concept of fields, such that the entity class just gets something, and what it gets is managed by a Property class for properties and by a Field class for fields, then the Field class can be defined in field.module, and my concern in #74 would be addressed, I think. I don't know if the idea has other problems though.

yched’s picture

I'm not sure the ability to make an entity that was not coded as "fieldable" into "fieldable" just by altering an info hook is something I'm really fond to serve as a base for the architecture :-/.

However, the other approach of having field values / entity properties ($entity->foo implements PropertyValueInterface / FieldValueInterface) is an idea I've been toying with myself, and could have many advantages.

$node->field_foo->view($formatter_name, $settings);
etc...

fago’s picture

Hm, I'm a bit embarrassed for not coming up with this earlier, but his approach reintroduces a hard dependency on field.module within entity.module, which is something other patches that went in earlier in the cycle tried to eliminate.

Thanks for catching that. We should not assume the entity is fieldable.
For now, I think it's fine to just check for the entity type being 'fieldable' as we already do in the storage controller. Beside being consistent, this also eases changing entity types from not fieldable to fieldable.

However, I agree that we want to separate the field api and the entity api better. The way I'd envision this is to move to a world in which an Entity just has properties, which optionally are fields. Thus, a field is just an entity property too but handled by the field module. -> See also #1346214: [meta] Unified Entity Field API.
Given that, we'd just have property info instead of field-info in the Entity class. Property (+field) values be accessed and modified in a unique way and the field module can work *on top* of that. It's about decoupling the storage system from the rest (yes field api should move out of the storage controller too).

Then, based upon entity property metadata we can provide improved getters/setters. E.g. they could directly return loaded entity objects, consistently for fields and non-fields:

// It's works the same way for a property
$account = $node->get('author');
// or a field.
$account = $node->get('field_user');
However, the other approach of having field values / entity properties ($entity->foo implements PropertyValueInterface / FieldValueInterface) is an idea I've been toying with myself, and could have many advantages.

I like this approach for compound data structures (as most fields are), but I'd prefer simple primitive properties/fields to be just plain simple data. We should probably move that discussion in its own issue though ;)

Gábor Hojtsy’s picture

Title: Add field/property get/set to entities with language support » Add generic field/property getters/setters (with optional language support) for entities

Retitling to make it clear it is not for "entities with language support". :)

aspilicious’s picture

Status: Needs review » Needs work

#965300: Change LANGUAGE_NONE to LANGUAGE_NOT_SPECIFIED; add LANGUAGE_NOT_APPLICABLE and LANGUAGE_MULTIPLE got in and I think we need to rename some stuff in this patch. Move status back if I'm incorrect.

fago’s picture

hm, the currently proposed EntityInterface::language() doesn't really fit anymore given that changes. It doesn't differentiate between different langcodes not pointing to valid languages.

Maybe we should additionally add EntityInterface::languageCode() ?

fago’s picture

Status: Needs work » Needs review
FileSize
13.68 KB

Attached patch does so. Also I've updated the patch to allow for translated values regardless of the defined language code. Previously the getters/setters reverted to LANGUAGE_NONE *always* if that was the entity language as my impression was: LANGUAGE_NONE means the entity is not translatable.

The new name LANGUAGE_NOT_SPECIFIED makes clear it still should be translatable. Not sure whether we should special-case on the other new language codes somehow. I guess we can deal with that in follow-up(s).

Status: Needs review » Needs work

The last submitted patch, drupal_entity_language-8.patch, failed testing.

fago’s picture

Status: Needs work » Needs review
FileSize
13.69 KB

? Re-uploading.

Gábor Hojtsy’s picture

@fago: well, so far the translation model we have for fields/entities in D7/D8 (since we did not make any changes to that yet in D8) is that unless the entity has a concrete language code, it is not translatable. The language code on the entity is used to store the language it was originally submitted in, that is one of the langcodes that you have fields available in. That is used as the base/source language for translations for example. It is used to display the edit form, as a default fallback language for displaying the entity, etc. So if you have a node that has LANGUAGE_NOT_SPECIFIED, that cannot really be a base for translation, can it? Can an unspecified language set of data be translated to German or English? I think as long as we keep that model going, if the entity has any special language code, it should not be translatable. It should only be translatable if it has a concrete language code (and its field configs say translatable for the respective fields).

fago’s picture

I'm not sure. I think in D7 it already happens that we've LANGUAGE_NONE entities with field-translation via the entity translation module, e.g. for terms? Also see #1376126-16: Fix language handling for translatable fields

Anyway, having an entity in LANGUAGE_NOT_SPECIFIED means that we just don't know the language to me, still it's language specific content and so it makes sense to me to have translatable fields on it, not? Sure, questionable is the assumed "source language" - probably just the site's default language?

Also that way you can start building a not multi-lingual site, turn on locale/language module later on and start translating your content. That's probably quite often desired in practice.

Gábor Hojtsy’s picture

That entity_translation did not add the language properties on entities such as terms yet is just a stop gap. I consider that a misbehavior not by design. Also, the addition of the language code is exactly so we know the language. If we make assumptions about entities where the user specifically said we should not make assumptions, then we don't follow our own rules. When you start off a not multilingual site, terms, nodes, etc. are saved in the site default language (practically English) until you enable language support, so we know the language of those very well. The purpose of the special language codes is to be used for special cases not to make our approach sloppier. :)

fago’s picture

ok, makes sense. Thus, if the entity has no certain language there should be no translations? If so, I'll re-roll the patch to convert to the previous behavior. I guess we should add EntityInterface::languageCode() anyways as it's necessary to get/distinguish between multiple language codes being no certain language (not specified, not applicable, ..).

Gábor Hojtsy’s picture

Right, if we are not certain of the language of the entity, it should not support translations.

fago’s picture

Updated the patch and the tests accordingly, please review.

plach’s picture

Status: Needs review » Needs work
+++ b/core/modules/entity/entity.class.inc
@@ -74,6 +74,70 @@ interface EntityInterface {
+  public function languageCode();

Having two methods to get the language *and* the language code might be confusing DX. We might want to remove this in the future if we are able to come up with a valid alternative.

+++ b/core/modules/entity/entity.class.inc
@@ -74,6 +74,70 @@ interface EntityInterface {
+  public function translations();

The translations() name might be misleading as the current field 'translatable' property is, since we are returning the available language variants. Which might not necessarily be translations. Again since this is fine for most use cases let's go on with it and figure out an alternative in a dedicated issue.

+++ b/core/modules/entity/entity.class.inc
@@ -245,6 +316,92 @@ class Entity implements EntityInterface {
+      // Go through translatable properties and determine all languages for
+      // which translated values are available.

We should move away form this approach in the long run, since we might have field values which are assigned a language but not belong any translation (linguistic shared fields). We probably should track this information with an internal property instead of computing it. For now this is covering the 90% of use cases, so I'd say it's fine.

+++ b/core/modules/entity/entity.class.inc
@@ -245,6 +316,92 @@ class Entity implements EntityInterface {
+      // Remove the default language from the translations.
+      unset($languages[$default_language->langcode]);

I don't think we should do this, this method should return all the available languages, even if there is only one. Only LANGAUGE_NOT_APPLICABLE and friends should not be returned. However while the name stays this might make sense.

+++ b/core/modules/entity/entity.class.inc
@@ -245,6 +316,92 @@ class Entity implements EntityInterface {
+    if (field_is_translatable($this->entityType, $field) && ($default_language = $this->language())) {

This could use a comment specifying why we ignore the $langcode parameter if the entity language is not available.

+++ b/core/modules/entity/tests/entity.test
@@ -65,6 +65,135 @@ class EntityAPITestCase extends DrupalWebTestCase {
+    // Set the value in a certain language. As the entity is not translatable it
+    // should use the default language.

This comment should be a little more clear about the fact that the language specified by the setter is actually being ignored.

+++ b/core/modules/entity/tests/entity.test
@@ -65,6 +65,135 @@ class EntityAPITestCase extends DrupalWebTestCase {
+    $entity->langcode = $this->langcodes[0];

We should have a language setter here in the long run.

5 days to next Drupal core point release.

fago’s picture

Status: Needs work » Needs review
FileSize
1.66 KB
13.92 KB

Having two methods to get the language *and* the language code might be confusing DX. We might want to remove this in the future if we are able to come up with a valid alternative.

Agreed. Once we'd have languages for the non-pure-language codes that could be removed.

The translations() name might be misleading as the current field 'translatable' property is, since we are returning the available language variants. Which might not necessarily be translations. Again since this is fine for most use cases let's go on with it and figure out an alternative in a dedicated issue.

Yep, let's keep it consistently with the field translatable key and change it all or nothing then :)

This could use a comment specifying why we ignore the $langcode parameter if the entity language is not available.

fixed that.

This comment should be a little more clear about the fact that the language specified by the setter is actually being ignored.

fixed it too, see the interdiff.

Updated patch and interdiff attached.

plach’s picture

Status: Needs review » Reviewed & tested by the community

Nice, let's get this in!

chx’s picture

I hope for followups that make the properties protected so people cant bypass set/get.

plach’s picture

@chx

I asked @fago the same but dynamic properties cannot be assigned a visibility.

fago’s picture

Status: Reviewed & tested by the community » Needs review
fago’s picture

Status: Needs review » Reviewed & tested by the community
KarenS’s picture

I think more documentation is needed for the confusing functions of languageCode() and language(). Currently one says "Returns the language code associated with the entity." the other says " Returns the default language of the entity." They return different values but that is not clear. Nor is it clear why they are so similar yet different. Plus if the goal is to deprecate one of them in the future, I think a comment about that should be made with an explanation. Does that mean developers should avoid using one of them? This is the kind of code that will make people tear their hair out in the future if not better documented :)

I didn't change the status because I don't want to derail progress, but I think those functions need a better explanation. I would try to provide a suggestion for improvement, but I don't understand the difference myself.

fago’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
1.14 KB
14.03 KB

I think more documentation is needed for the confusing functions of languageCode() and language().

Indeed, the difference wasn't that clear. Attached patch tries to improve it (includes interdiff).

Plus if the goal is to deprecate one of them in the future, I think a comment about that should be made with an explanation.

Well, the issue is that's not for sure as it pretty much depends on the outcome of related issues like #1471432: Rework language_list(), let people use more special languages which might add those language codes as valid languages or not. So I'd suggest just coming back to this one if it turns out to work that way.

KarenS’s picture

Status: Needs review » Reviewed & tested by the community

I think that is much more clear, thanks! I didn't test this but others have and the only change is the terminology, so marking it back to reviewed and tested.

xjm’s picture

I noticed a couple small oddities with the docs:

  1. +++ b/core/modules/entity/entity.class.incundefined
    @@ -245,6 +319,94 @@ class Entity implements EntityInterface {
    +    // @todo: Check for language.module instead, once field API language
    +    // handling depends upon it too.
    

    SUPER nitpicky, but I think "Field API" should be capitalized.

  2. +++ b/core/modules/entity/tests/entity.testundefined
    @@ -65,6 +65,135 @@ class EntityAPITestCase extends DrupalWebTestCase {
    +    // Also getting a translated value should go with the default language.
    

    I don't quite understand this comment.

  3. +++ b/core/modules/entity/tests/entity.testundefined
    @@ -65,6 +65,135 @@ class EntityAPITestCase extends DrupalWebTestCase {
    +    // Try to get a not available translation.
    ...
    +    $this->assertNull($value, 'Not available translation is NULL.');
    

    "Not available translation" isn't really idiomatic. "A translation that is not available" would be better.

Not touching the status because these are so minor they could easily be moved into a followup instead, and not rerolling myself since I don't know what the comment in my second point above is actually saying. :)

Lars Toomre’s picture

I think our best practice for D8 recommends type hinting for @param and @return directives. Hence, I was surprised to see that there were none in EntityInterface. Should type hinting be added here?

Gábor Hojtsy’s picture

Status: Reviewed & tested by the community » Needs work

@xjm: ok, so the code for the second comment you highlighted looks like it creates an entity without assigned language, but then attempts to load a field with a specific language. Since the entity has no assigned language, it should fall back in that case to the value then entity was created in. That is being tested. Good ideas to reword that?

saltednut’s picture

Status: Needs work » Needs review
FileSize
14.07 KB

- Updated comments in patch per xjm's revisions in c100.
- "Also getting a translated value should go with the default language." -> "Entity has no assigned language. Field should default to the language the entity was created in."

Gábor Hojtsy’s picture

Status: Needs review » Reviewed & tested by the community

Comment only changes. Should be back to RTBC then.

Dries’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/entity/entity.class.incundefined
@@ -74,6 +74,73 @@ interface EntityInterface {
   /**
+   * Returns the language code associated with the entity.
+   *
+   * The language code of the entity either refers to a language or to one of
+   * the system language constants, e.g. LANGUAGE_NOT_SPECIFIED,
+   * LANGUAGE_NOT_APPLICABLE or LANGUAGE_MULTIPLE.
+   *
+   * @return
+   *   A valid language code.
+   */
+  public function languageCode();
+
+  /**
+   * Returns the default language of the entity.
+   *
+   * @return
+   *   The language object of the entity's default language, or FALSE if no
+   *   valid language is assigned.
+   *
+   * @see EntityInterface::translations()
+   * @see EntityInterface::languageCode()
+   */

It is not clear why we need both. I expected only one of those to exist. It took me a while to understand the difference. I think it makes the Interface more confusing and less clean.

+++ b/core/modules/entity/entity.class.incundefined
@@ -245,6 +319,94 @@ class Entity implements EntityInterface {
+  /**
+   * Determines the language code to use for a field.
+   */
+  protected function getFieldLangcode($field, $langcode = NULL) {
+    // Only apply the langcode if the entity is language specific, thus has a
+    // language assigned.
+    if (field_is_translatable($this->entityType, $field) && ($default_language = $this->language())) {
+      return isset($langcode) ? $langcode : $default_language->langcode;
+    }
+    else {
+      // Non-translatable fields always use LANGUAGE_NOT_SPECIFIED.
+      return LANGUAGE_NOT_SPECIFIED;
+    }

I'm not sure this logic makes sense. In the if-clause, we return the specified $langcode even if it may not have been set? The getFieldLanguage() API seems a bit weird. You enter a $langcode and then you get a $langcode back? I would not expect one to pass in a $langcode. It needs a bit more documentation before I can make sense of that.

fago’s picture

Status: Needs work » Needs review
FileSize
4.19 KB
14.56 KB

It is not clear why we need both. I expected only one of those to exist. It took me a while to understand the difference. I think it makes the Interface more confusing and less clean.

True. Still, I think we'll need a way to generally access the language code as well as a simple way to get the language object for language-specific entities. So I tried to improve the docs of both methods by clearly noting that we have a "language-specific entity" and a "not language-specific entity" case. I hope this helps to point out why we have both, please review.

#103 contained a comment exceeding 80 chars, fixed that + improved the test-comments to also make use of the "language-specific" wording.

@getFieldLanguage():

I'm not sure this logic makes sense. In the if-clause, we return the specified $langcode even if it may not have been set?

No, if it's not set we return the language code of the default language.

The getFieldLanguage() API seems a bit weird. You enter a $langcode and then you get a $langcode back? I would not expect one to pass in a $langcode. It needs a bit more documentation before I can make sense of that.

getFieldLanguage() is only a private helper, so one should not have to care about it.
Anyway, I've tried to improve its comments a bit so it is easier to get. In the long run, field API language handling should not differentiate from the general property language handling, so hopefully we can do away with it then.

Updated patch + interdiff attached.

Gábor Hojtsy’s picture

@Dries, @fago: in fact in #1471432: Rework language_list(), let people use more special languages we are leaning towards making the special languages part of the regular language list, ie. let people disable them, so they cannot be assigned to nodes lets say, or reorder them, so they show up in their priority order for content assignment, etc. That would need all kinds of filtering so they don't show up in a language switcher block let's say. So there are quite a few odd ends to resolve there before we can make them generally available as such. I think moving forward with the entity/field/property API is of paramount importance that it should not be held back for unresolved questions in this related field. If we introduce language objects like that, then we can return here and drop one of the API functions to clean it up. We can also introduce langcode return only for now and return later to the language object question, if that sounds better.

plach’s picture

We can also introduce langcode return only for now and return later to the language object question, if that sounds better.

+1

Also:

+++ b/core/modules/entity/entity.class.inc
@@ -392,12 +396,14 @@ class Entity implements EntityInterface {
+   * Determines the language code to use for accessing a field value in a certain language.

This line exceeds 80 chars. It seems the latest coding standards do not allow even PHP doc summay lines to go over column 80. What about the following?

Determines the language code to use to access a field in a given language.
fago’s picture

We can also introduce langcode return only for now and return later to the language object question, if that sounds better.

Still, we need an easy way to differentiate between language-specific and not language-specific entities. I think that's something one should be able to easily check for so language-requiring features of modules can be easily turned on/off. We'll need that ourself in the Entity class too (see getFieldLanguage()).

Currently, it's as easy as doing:

if ($language = $entity->language()) {
 // Code requiring language here.
}

Without that though, it'd be quite cumbersome to have to
1. retrieve the language code and either
2.a check for one of the defined language code constants being no certain languages or
2.b try to load the language yourself

fago’s picture

@80chars:

Afaik the first line may exceed 80chars. I found that example in the coding standard docs:

* Summary here; one sentence on one line (should not, but can exceed 80 chars).

So I don't think it makes much sense to deform sentences just to fit the 80chars?

Gábor Hojtsy’s picture

@fago: yes, that is a very good goal I fully agree with BUT I don't know we want to block this patch on that. Once again the direction of #1471432: Rework language_list(), let people use more special languages is that you are going to get a language object for special languages, but it is going to have its own property by which you can tell it is a special (non-configurable) language. That property used there is currently $language->locked (in accordance with content types which have a similar pattern for non-editable code defined objects). We can certainly make up something better for that there, BUT this patch introduced definitely some important things, and we can return to the special language problem once that is there. This was held back for a looong time IMHO.

fago’s picture

>Still, we need an easy way to differentiate between language-specific and not language-specific entities.

@fago: yes, that is a very good goal I fully agree with BUT I don't know we want to block this patch on that.

Well, we need this functionality even *in* this patch. Additionally I think it really belongs to the interface such that people can easily check for language aware entities.
Actually, *if* we are dropping something I'd prefer to drop languageCode() instead of language() as I'd consider the differentiation between those system constant language codes quite unimportant compared to being able to check whether an entity is language-specific.

Thus, I think we should either go with a patch containing improved documentation as #106 or drop EntityInterface::languageCode(). So any feedback on #106?

Gábor Hojtsy’s picture

I'm fine with either so as long as we don't wait on #1471432: Rework language_list(), let people use more special languages being resolved, which can take on considerable time still.

plach’s picture

I'm ok with going back to #106 (not sure if it'll pass the coding standards check ;), an alternative could be to have a (possibiliy temporary) method to detect the type of the system langcode assigned to the entity (if any). Something like

<?php

/**
 * Implements EntityInterface::systemLanguageCode().
 *
 * This replaces EntityInterface::languageCode().
 */
function systemLanguageCode() {
  return !$this->language() ? $this->langcode : FALSE;
}

?>

which would be used only when $entity->language() is false.

Gábor Hojtsy’s picture

FileSize
13.82 KB

Rerolled with languageCode() method removed. I think the utility of this patch far outshines this (IMHO) minor question as to how we deal with special language codes temporarily before we add them as real looking languages stamped as special in #1471432: Rework language_list(), let people use more special languages. I think we have been attached to so many little details of this patch that if we keep doing it, it will never get in :/ Looks like @fago agrees just getting rid of languageCode() keeps us the interface we needed to be able to tell for how whether we had a special language code or not, while also making the language info clearly available. That seems to be pretty good for me.

Status: Needs review » Needs work

The last submitted patch, drupal_8_language_2.patch, failed testing.

Gábor Hojtsy’s picture

Status: Needs work » Needs review
FileSize
13.81 KB

Mistyped $this->langcode as $this->langucode.

fago’s picture

Looks like @fago agrees just getting rid of languageCode() keeps us the interface we needed to be able to tell for how whether we had a special language code or not, while also making the language info clearly available. That seems to be pretty good for me.

Yep, let's do that.

+++ b/core/modules/entity/entity.class.inc
@@ -276,6 +337,89 @@ class Entity implements EntityInterface {
+    return module_exists('locale') ? language_load($this->langucode) : FALSE;

Here's a typo. Fixed that. -> Updated patch attached.

Note: I'm using the Git branch 8.x-entity-lang from over here to create patches and interdiffs. There is no clean history for pulling it into core, but you can use it to re-roll/update the patch. @Gabor, plach: I've granted you access - anyone else just ping me.

fago’s picture

hm, crossposted.

Gábor Hojtsy’s picture

Status: Needs review » Reviewed & tested by the community

Ok, we have arrived at the same thing. This satisfies Dries' concern in a way that fit well with other reviewers. Let's get this in. We can revisit this later after #1471432: Rework language_list(), let people use more special languages.

catch’s picture

Title: Add generic field/property getters/setters (with optional language support) for entities » Change notification for: Add generic field/property getters/setters (with optional language support) for entities
Priority: Normal » Critical
Status: Reviewed & tested by the community » Active

Committed/pushed this to 8x. One hunk didn't apply (in Entity::__construct()) but it's no longer a relevant change I think, we'll find out if HEAD breaks in the next 20 minutes..

This will need a change notification

catch’s picture

Priority: Critical » Major
Status: Active » Needs work

Nope, this did break HEAD so I've rolled it back, could we get a re-roll?

catch’s picture

Title: Change notification for: Add generic field/property getters/setters (with optional language support) for entities » Add generic field/property getters/setters (with optional language support) for entities
tim.plunkett’s picture

Status: Needs work » Needs review
FileSize
13.34 KB

Here's a stab at this. Let's wait for the bot on this one :)

Status: Needs review » Needs work

The last submitted patch, drupal-1277776-124.patch, failed testing.

tim.plunkett’s picture

Status: Needs work » Needs review
FileSize
15.35 KB

Okay, last try for the night.

Status: Needs review » Needs work

The last submitted patch, drupal-1277776-126.patch, failed testing.

fago’s picture

FileSize
13.45 KB

oh, patch broke due to the commit of #1512564: Remove entity info from the Entity classes, thus $this->entityInfo is gone. Re-rolled it.

fago’s picture

Status: Needs work » Needs review
Gábor Hojtsy’s picture

Status: Needs review » Reviewed & tested by the community

Looks good, thanks for the re-roll.

fago’s picture

Status: Reviewed & tested by the community » Needs review
Berdir’s picture

Status: Needs review » Reviewed & tested by the community

crosspost by fago, back to RTBC.

fago’s picture

Status: Reviewed & tested by the community » Needs review

ops, thanks

fago’s picture

Status: Needs review » Reviewed & tested by the community

:D

catch’s picture

Title: Add generic field/property getters/setters (with optional language support) for entities » Change notification for: Add generic field/property getters/setters (with optional language support) for entities
Priority: Major » Critical
Status: Reviewed & tested by the community » Active

Alrighty, trying again!

plach’s picture

Ok, now we need to get the backports in ;)

Gábor Hojtsy’s picture

Added an initial change notice at http://drupal.org/node/1532946. @fago or @plach can you help with before / after code examples of how the getter/setter simplifies accessing/setting fields / properties? :) Would be good to set this fixed then (and set back the status accordingly).

plach’s picture

Title: Change notification for: Add generic field/property getters/setters (with optional language support) for entities » Add generic field/property getters/setters (with optional language support) for entities
Priority: Critical » Major
Status: Active » Fixed
Issue tags: -sprint

Added a couple of code snippets. I think this can be called fixed, yay!

fago’s picture

Added another simple example for translation access - looks good to me now. :-)

pounard’s picture

The EntityTranslationTestCase test case could almost be a unit test case (and be a lot faster to run).

sun’s picture

Status: Fixed » Needs review
FileSize
1.41 KB

Follow-up patch to decouple EntityTranslationTestCase from the parent site environment executing the test.

Please don't do such couplings.

xjm’s picture

Status: Needs review » Reviewed & tested by the community

Ick, yes. :)

tim.plunkett’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/entity/tests/modules/entity_test/entity_test.moduleundefined
@@ -20,7 +20,7 @@ function entity_test_entity_info() {
+  if (variable_get('entity_test_translation')) {

Shouldn't this be variable_get('entity_test_translation', FALSE)

sun’s picture

Status: Needs work » Reviewed & tested by the community

Doesn't matter, NULL is as good as FALSE.

Gábor Hojtsy’s picture

Issue tags: +sprint

Back on sprint for easier tracking.

catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.x.

Gábor Hojtsy’s picture

Issue tags: -sprint

Thanks.

Status: Fixed » Closed (fixed)

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

TravisCarden’s picture

Re-tagging.

TravisCarden’s picture

Issue summary: View changes

fixed issue reference