Problem/Motivation
It needs to be possible to import content into multiple languages. Right now, Feeds can only import values for one language at a time.
The user must be able to select per mapping field for which language to import a value.
Proposed resolution
To be determined. There is a patch available that seems to work for some people.
Remaining tasks
- Add general test coverage for emptying values:
#3103561: Add basic test coverage for clearing out values For the bug reported in #3090788: Unable to import file: undefined method getCardinality(), add test coverage + fix #2994668: Values duplicate when mapping multiple columns to one multi-value text field- Clean up code: add code comments, comply to coding standards.
- Determine which tests from the D7 version should (still) be ported:
FeedsMapperMultilingualFieldsTestCase::testChangedLanguageImportForExistingNode()
FeedsMapperMultilingualFieldsTestCase::testAutocreatedTermLanguage()
FeedsMapperMultilingualFieldsTestCase::testClearOutValues()
Maybe a few others from FeedsMapperMultilingualFieldsTestCase.
- Fix concerns reported in #49.
User interface changes
The user can select per mapping field in which language the value must be imported.
API changes
To be identified.
Data model changes
To be identified.
Original report by takim
I have a multi language site where i need to import content from RSS. But unfortunately i need to import it into different language and i cant find out a way? I do not see language field in target mapping page as well.
Any idea or how to fix it ?
/takim
Comment | File | Size | Author |
---|---|---|---|
#108 | interdiff-2829283-104-108.txt | 4.89 KB | MegaChriz |
#108 | feeds-content-translation-2829283-108.patch | 55.87 KB | MegaChriz |
| |||
#97 | feeds-content-translation-2829283-97.patch | 49.11 KB | MegaChriz |
#78 | mapping-76.png | 32.34 KB | toprak |
#72 | feeds-content-translation-2829283-72.patch | 37.57 KB | MegaChriz |
Comments
Comment #2
MegaChriz CreditAttribution: MegaChriz as a volunteer commentedLanguage support hasn't been ported to the D8 version yet. It will be ported after the base features of Feeds 8.x-3.x are finished. See also #1960800: [meta] Feeds 8.x roadmap. Porting features is listed as step 4 there.
I have found some people who may want to help with continuing the port (the port is put on hold at the moment). Hopefully, we can start with that in early 2017.
Comment #3
takim CreditAttribution: takim commentedOkay i found out a way to fix it. I have added language target in my module. Making a new cision_feeds module to import Cision feeds based on Feed module. It fix my issue. But it would be nice i might make a patch so it should be included in Language Target in the Base feed module.
Comment #4
MegaChriz CreditAttribution: MegaChriz as a volunteer commentedA patch is always welcome. :) It might take a while though before it gets a review.
Comment #5
kumkum29 CreditAttribution: kumkum29 commentedHello Takim !
Can you precise what is your method to import contents with different languages? For this time, we haven't this option in the feeds module. Can you share your solution for the maintainers of feeds module? This option is essential for the multilingual sites.
Thanks.
Comment #6
takim CreditAttribution: takim commentedOkay, i will share it soon. I might be add patch for this.
Comment #7
arskiainen CreditAttribution: arskiainen at Mirum Agency commentedWe also ran into this issue and would appreciate some info on how you fixed this. We don't want to reinvent the wheel.
Comment #8
takim CreditAttribution: takim commentedI have created a dev module for this. you can look into code.
https://www.drupal.org/project/cision_feeds
If you want to use Push notification from Cision you can check my this module
https://www.drupal.org/project/cision_notify_pull
Comment #9
arskiainen CreditAttribution: arskiainen at Mirum Agency commentedThe Cision Feeds module has the source mapping for the language, but there is no mapping target for the langcode.
Here is a simple patch that works for me. I only added a Language target definition, where the main point is the annotation.
Anyone feel free to add tests and perhaps validation / cleanup for the langcode formatting, if deemed necessary.
Comment #10
pvbergen CreditAttribution: pvbergen as a volunteer commentedWe have to import several different types of content in four languages and the feeds module is great to get the data into Drupal. However, we need all four languages to be translations of the same entity. Based on the discussion and after studying I've had a look at making the import multilingual as well.
Outline of my approach
- Use the language target plugin of @arskiainen to provide a suitable target field in the mapping.
- Check the value provided for the language target and load or create the entity in the corresponding language.
- Pass the entity in the correct language to hashing, map(), validate etc. and skip setting the langcode field (this would throw an error in Drupal Core, see https://www.drupal.org/node/2443989).
This approach allows to get the language code from the imported file and assumes that there is a unique value across all languages (e.g. an common id within the import data). One still has to create one feed per language though, which is okay for us though.
I've tested the code with our XML based imports and one unique field.
Let me know if you see any problems with my approach or code. I haven't used the feeds module before today, so I might have very well missed something.
Comment #12
MegaChriz CreditAttribution: MegaChriz as a volunteer commentedThanks for your efforts, @pvbergen
Ideally the language solution would follow a similar approach as in the D7 version of Feeds. Can't the language be set during mapping? Does it need to happen before setting other values?
Comment #13
pvbergen CreditAttribution: pvbergen as a volunteer and at iqual AG commentedThanks for your quick response, MegaChriz! I have never used feeds in Drupal 7, so I can't tell how close my solution is.
In the approach in #10, you can indeed select the language as a target field in the mappings and it can be at any position.
Below is a screenshot of one of my tests, where you can see the setup (with XML/xpath parser from feeds_ex).
Comment #14
MegaChriz CreditAttribution: MegaChriz as a volunteer commented@pvbergen
I meant: can the language be changed after having set other values on the entity first in code?
For example (pseudo code):
Ideally, the code that sets the language of the entity would live in
\Drupal\feeds\Feeds\TargetLanguage::setTarget()
instead of in EntityProcessorBase.Comment #15
pvbergen CreditAttribution: pvbergen as a volunteer and at iqual AG commentedI now understand what you mean MegaChriz. I actually wanted to do this very thing first, setting/updating the language in
\Drupal\feeds\Feeds\TargetLanguage::setTarget()
.As far as I'm aware, this only works when you want to change the langcode of the entity translation. E.g. updating a Dutch translation to be the English translation, effectively removing the Dutch translation of the entity.
To add a new translation in another language while keeping the old translation,
\Drupal\Core\Entity\ContentEntityBase::addTranslation
has to be used.The function creates a translation of the entity and stores it to the database immediately. That's why one has to give a value array as the second parameter, containing at least the title, too.
The processor needs to get/add a translation before any values are being set, hence the changes in EntityProcessorBase.
I guess your questions stems from the thought to allow hooks/subscribers/heirs to act upon the langcode before it is set.
I don't really have a solution for that..
Comment #16
westerix CreditAttribution: westerix commentedFacing a similar D8 challenge (working with multiple languages) and, following the suggestions above, have introduced the patches #9/#10 above and that's provided 'Language' target option.
However, when attempting to import a translation, it fails with "Provided language is not installed" using default English [en] to successfully create the node and then introducing German [de] translation it topples.
Working with the simplest source possible, eg
Tried multiple ways to address langcode to no avail. Am I missing something obvious?
Update/overlooking the obvious:
After running through, debugging values, etc I finally noticed that the langcode in languages array check was always throwing a fail when the langcode was found in the array of enabled languages.
Adding a '!' to line 131 of feeds/src/Processor/EntityProcessorBase.php...
if (!in_array($langcode, $languages)) {
...appears to create a reliable enough multi-lingual import for now.
Comment #17
FrancescoQ CreditAttribution: FrancescoQ commentedHi! Thanks, i've tested #10 and works for me adding the suggestion in #16.
I attach the modified patch here (also applying with composer the #10 didn't work, it seems some enconding problem, now i try with the one i'm attaching.)
Comment #18
anthonybr CreditAttribution: anthonybr commentedThank you
Comment #19
anthonybr CreditAttribution: anthonybr commentedHello, I do not find how to import several languages. I did the update but nothing. Can you tell me how do you do it?
Comment #20
bibo CreditAttribution: bibo commented#17 works ok for me (for a single language). Setting to Reviewed and tested.
@MegaChriz can we get at least this simple language support in the next feeds dev and alpha versions?
We desperately also need feeds multilngual entity support (entity translations) soon, but at please commit this stuff first?
Comment #21
ReViJa CreditAttribution: ReViJa commentedHello everyone,
To me the patch # 17 in localhost did not work with:
Drupal 8.6.1
Apache / 2.4.33 (Win64) OpenSSL / 1.1.0h PHP / 7.0.25
It would be good to work in this field.
Thank you very much for your work.
Comment #22
bibo CreditAttribution: bibo commented@ReViJa
You should be more specific how it did not work with D8.6.x? I've also upgraded to D8.6.x, but the language mapping is working for me currently.
However I had to create workaround for a D8.6.x issue related to translations and probably content_moderation. Without an entity alter hook I'd get this validation error for everything:
"Unable to change non-translatable field value on translatable content with content "
More info:
* https://www.drupal.org/node/2938191 / New API to specify whether changes to untranslatable fields should affect only the default revision translation
* https://www.drupal.org/project/drupal/issues/2955321 / Unable to change non-translatable field value on translatable content with content moderation enabled.
* https://www.drupal.org/project/drupal/issues/2878556 / Ensure that changes to untranslatable fields affect only one translation in pending revisions
* https://www.drupal.org/project/drupal/issues/2959175 / Non-translatable fields error when using: Content Moderation + Content Translation + Comments
* https://www.drupal.org/project/drupal/issues/2955321 / Unable to change non-translatable field value on translatable content with content moderation enabled
*
* Related drupal API changes, setting which solves this in some cases, but moderation and feeds complicate this.
* https://www.drupal.org/node/2938193 / New option to hide untranslatable field widgets
* https://www.drupal.org/node/2950608 / Content translations can be moderated independently
* https://www.drupal.org/project/drupal/issues/2950626 / Allow flagging translations as outdated when content is moderated
NOTE: I'm still having other issues, especially related to content_moderation.
Comment #23
bibo CreditAttribution: bibo commentedGood news: the language import works actually pretty nicely even with translated content (shared guid).
The origin language flag doest not need to be mapped, there were problems.
However, content_moderation breaks the import fully for every translation , so I created a new issue about that:
https://www.drupal.org/project/feeds/issues/3002606
Comment #24
bibo CreditAttribution: bibo commentedA new issue I found with latest patch:
It seems that feeds tamper is not executed early enough, validation fails before that.
For example if the language source is set by a tamper plugin default value, it doesnt work but fails because of this line:
$state->setMessage('Provided language is not installed.', 'warning');
How to make feeds tamper run correctly before validation?
Comment #25
MegaChriz CreditAttribution: MegaChriz at WebCoo commentedI can understand the high need for this feature, but I think the current implementation make things less maintainable as it special cases the langcode target. I haven't been working on multilingual sites in D8 yet, but it seems the code is also adding support for translations beside just setting the entity's language:
What I would like to see is the following:
Anyway, update the issue summary to clearly reflect what this issue tries to solve (and what it does not try to solve - yet).
Comment #26
omarlopesinoHere is a patch that continues work from #9
In this patch the following improvements are done:
- Set langcode using ->set method from entity (@see drupal answer mentioned in #25 https://drupal.stackexchange.com/questions/240086/how-to-update-the-lang...).
- Allow set, for each mapping field, in which language set the entity field value. If empty uses default language. To test it you need add a multilanguage field in mapping, and you could select language in configuration.
Here is an screenshot of it:
With this patch a complete language support should be done.
Tests are still pending but code and behaviour can be reviewed.
Please review, thanks!
Comment #28
omarlopesinoAdding new patch with the following changes:
- Correct dependency test, it was failing because the changes alter the default config for feed targets.
- Add tests for language.
- Add tests for content translation.
- Set correct author for content translation, it was not being correctly set before.
Adding to Needs review again.
Comment #30
MegaChriz CreditAttribution: MegaChriz as a volunteer commented@mistermoper
Thanks for working on this. And for providing tests! Would it be possible for you to break the patch down into smaller changes? That makes it easier to review for me. So separate the language target from content translation support. Else it would simply take me weeks before I fully reviewed and tested the patch (it may even be months as I have other things that need my attention too). To start, a patch that just provides the language target would be the easiest I think.
Comment #31
omarlopesinoOk then i will upload both features in different patches.
Here is a patch which allows make a mapping of language. Interdiff is from patch #9.
Comment #32
omarlopesinoHere is the patch for content translation.
I have updated the summary to indicate which patches need to be applied in each case.
Comment #33
omarlopesinoComment #34
MegaChriz CreditAttribution: MegaChriz as a volunteer commented@mistermoper
Thanks, I hope I can take a look at these patches soon. It's very likely though that this needs more tests. In the D7 version of Feeds, there were a lot of tests for this.
See for example FeedsMapperMultilingualFieldsTestCase, which tested (among more) the following cases:
In #1183440-234: Multilingual Feeds - Make field import language-aware you can see how I tackled this issue for the D7 version.
Ideally, we would have above cases all covered. Else we could also mark language support as experimental. I don't want this issue sit here for another two years. Anyways, I need to plan in some time to review both patches.
Comment #35
omarlopesinoI am starting with this.
There is, among others, one feature which is missing in these patches: allow set the language in the node processor, now is only possible by mapping. Is this required for a stable version?
Meanwhile, I will start covering this use case "If values from other language are kept when not importing values for that language." with field mappings.
Comment #36
MegaChriz CreditAttribution: MegaChriz as a volunteer commented@mistermoper
That would be great if you want to write a test for that!
About language set on the processor - the D7 version of Feeds had this. I think it would be useful to have in the D8 version as well. But not in this issue. Perhaps it would be better to split this issue up into three issues - one for each feature - and label this as a meta issue. The two features so far handled in this issue are already split apart into two patches, which is great as that allows us to focus on one feature at a time.
Comment #37
yurg CreditAttribution: yurg commentedSeems #31 applies fine against alpha, but #33 requires 3.x-dev; haven't been able to get language name for Language in Mapper, after #31 has been applied though.
But after Feeds 3-x dev was installed, I've got "Class 'Drupal\feeds\Feeds\Target\Language' not found in Drupal\feeds\Entity\FeedType".
Hope it will help someone.
Comment #38
anthonybr CreditAttribution: anthonybr commentedHello,
It's not possible to apply a path.
I dont have a configure checkbox import languages.
It's possible to send me a complete working feed folder please ?
Thank you
Antho
Comment #39
Flodevelop CreditAttribution: Flodevelop commentedHello,
Here is my feedback.
The 2 patches need to be applied on a previous dev version (commit #72bed0603893ca814a159919d14cb7564b6d2a2e).
If you have composer you can do this by adding the patches in your composer.json file :
And require the specific dev version :
composer require 'drupal/feeds:3.x-dev#72bed0603893ca814a159919d14cb7564b6d2a2e'
Tested ok on a term entity.
Tested on single formated textfield.
Have some others difficulties :
- need to duplicate the unique field in the other languages to avoid some SQL error.
- when update existing entity formatted text field, it doesn't replace the value but create another item in the fieldItemList despite the fact that the field is limited to 1 so the value is lost. Need to setValue of this on a hook_presave to fix it.
- Have some bad encoding characters éàù... need to utf8_encode the imported field on hook_presave.
Thank you all for your work !
Comment #40
omarlopesinoSorry for taking so many time to do this.
Attaching a new patch with some Tests to cover use cases #36, except for use case 'How values are imported after a language gets disabled. It may be that in D8 you cannot disable a language if configuration depends on it. I haven't checked that.' because there is no way to disable a language in Drupal 8. This changes made the code change as some checks were not working.
This tests is not prepared yet 'When importing empty values for a certain language, ensure that values for that language are wiped out (and not for other languages).
'.
Can you check this? Thanks!
Comment #42
omarlopesinoAttaching a new patch, making the tests with the new Feeds API.
Comment #43
omarlopesinoComment #44
MegaChriz CreditAttribution: MegaChriz as a volunteer commented@mistermoper
Thanks for continuing to work on this. I'd like to review it, though I have other Feeds relates issues that I'd like to address first. These are:
#2971881: Plugins that depend on a tamperable item need to know the available properties
#2976180: Rewrite Plugin
#2799225: The "hidden" plugin does not exist: Drupal\Component\Plugin\Exception\PluginNotFoundException:
Once these are resolved, I can address this one.
Comment #46
MegaChriz CreditAttribution: MegaChriz as a volunteer commentedI have tested the patch from #31 that provides a target to language.
I tested also with specifying a language that did not exist on my install and that import failed with a validation error:
Looks like expected behavior to me.
The patch has tests, so is good to go. So committed #31.
This issue remains open for content translation support. #42 has the latest patch for this feature.
Comment #48
MegaChriz CreditAttribution: MegaChriz as a volunteer commentedApparently, the patch in #31 caused some test failures. That's probably because I slightly changed the implementation for
createFeedTypeForCsv()
a few months ago. Corrected that. Also saw that the test used the deprecated 'entity.manager' service. Replaced that with the 'entity_type.manager' service on commit.Comment #49
MegaChriz CreditAttribution: MegaChriz as a volunteer commented@mistermoper
Thanks again for your work! I finally started with looking at your patch from #42. Sorry it took so long.
Here is my code review:
I don't think all these methods have to public. And the methods that do would need to be defined in an interface.
This requires the method
getLanguage()
to be defined in an interface. Then the code here can check if that interface gets implemented.Maybe getting
$group
should be moved to a protected method? Further in the codegetLanguage()
is called again on a target plugin (which by the way misses the fallback to 'default' there).A check for if the target plugin implements
getLanguage()
is missing here.Should have a fallback to 'default', I guess?
According to the implementation of
FieldTargetBase::getEntityTarget()
, that method could returnNULL
.Nitpick: the use statements should be in alphabetical order.
Checking the cardinality here makes me think the following: in the case that there are additional values, the values would get simply ignored without the user noticing?
If it is to minimize failing imports then I agree that these can be annoying, but ignoring input without the user knowing is bad as well. Therefore I think that the cardinality check should be removed here.
It's completely valid to import empty values. Therefore I think that this method needs to be removed.
Example: say you are importing user profiles and you are regularly updating these with subsequent imports. Then an user wants his phone number to be removed. You remove it on the source and then you expect it to be removed on the target site on the next import as well.
Missing docblock.
Nitpick: redundant space before comma.
Interfaces/classes should be documented with their full namespace, according to the Drupal coding standards.
getEntityTarget()
can returnNULL
if the language does not exist, but that's not documented in the method. In point 5 I already mentioned that code calling this method is expecting an entity.Missing docblock.
showSummary()
doesn't entirely fit what the method does. It doesn't show anything. PerhapsformatSummary()
would be better?I haven't looked at the tests yet, but I plan to do so.
Comment #50
BarisW CreditAttribution: BarisW at LimoenGroen commentedThanks all for working on this patch! Working on a large Dutch project and this patch is really helpful to import Dutch/English content.
However, I found that the patch in #42 doesn't apply anymore to dev, so here's a re-roll against HEAD.
Comment #51
BarisW CreditAttribution: BarisW at LimoenGroen commentedAlso added an interdiff to keep track of changes
Comment #52
le72Hi, I have three languages Drupal 8 and taxonomy CSV in all three languages (Name_lang1, Name_lang2, Name_lang3). I try the #50 patch. Processed with success but I can view only terms in the original language. The translation tab contains other two languages translation, but if I click (view) the translation I get an error:
.
Any help will be appreciated.
Comment #53
MegaChriz CreditAttribution: MegaChriz as a volunteer commentedThis patch needs a reroll.
Additionally, there’s probably a bug in
FieldTargetBase::setTarget()
:+ if (!empty($item_list->getValue()) && $item_list->getFieldDefinition()->getCardinality() > 1) {
FieldDefinitionInterface doesn’t have a method called
getCardinality()
, which can result in a undefined method error as reported in #3090788: Unable to import file: undefined method getCardinality().Also, I asked in #49 why the cardinality check is necessary:
Comment #54
MegaChriz CreditAttribution: MegaChriz as a volunteer commentedI'm doing a reroll for now, still needs work as of #49.
Next step would probably be to port tests for emptying values (non-language related), to ensure that keeps working with the changes from the patch here.
Step after that would be adding test coverage for the bug reported in #3090788: Unable to import file: undefined method getCardinality().
Comment #55
LOBsTerr CreditAttribution: LOBsTerr commentedI have tried the patch, when I try to save the form with language I get "The machine-readable name is already in use. It must be unique." and all machine name fields marked as the wrong one, even they have been generated and they look quite unique.
I have tried to replace them with really unique name I still have the same result.
If I don't choose any language it will save the same machine name correctly.
Comment #56
camoa CreditAttribution: camoa at Acquia commentedPatch 54 is failing on the Current feeds dev branch.
Comment #57
matthieu_collet CreditAttribution: matthieu_collet commentedSame here, Patch 54 is failing on the Current feeds dev branch and Drupal 8.7.10
Comment #58
MegaChriz CreditAttribution: MegaChriz as a volunteer commented@camoa, @matthieu_collet
The patch in #54 is applying fine on the latest dev in my case. Could it be that you do have some other patches applied as well? Or do you mean that you get errors in the user interface after applying the patch?
Comment #59
matthieu_collet CreditAttribution: matthieu_collet commentedHi @MegaChriz
I have an error in composer, it says it's not applied, but it seems that it is and it works. And i don't have other patches for Feeds
I just now have an error with line 88 of FieldTargetBase.php
if (!empty($item_list->getValue()) && $item_list->getFieldDefinition()->getCardinality() > 1) {
Call to undefined method Drupal\field\Entity\FieldConfig::getCardinality() in Drupal\feeds\Plugin\Type\Target\FieldTargetBase->setTarget() (line 88 of /home/dkvision/staging/correct-immo.be/modules/contrib/feeds/src/Plugin/Type/Target/FieldTargetBase.php).
so I replaced "$item_list->getFieldDefinition()->getCardinality() > 1" by "0 > 1" so it's denied, and it works now, I imported content types in 2 languages
Comment #60
fbreckx CreditAttribution: fbreckx commented@ Matthieu: what did you replace exactly? Like this?
if (!empty($item_list->getValue()) && $item_list->getFieldDefinition()->getCardinality() > 1)
to
if (!empty($item_list->getValue()) && 0 > 1)
?
Comment #61
MegaChriz CreditAttribution: MegaChriz as a volunteer commentedI've opened a spin-off issue for adding test coverage for clearing out values: #3103561: Add basic test coverage for clearing out values.
I also have the suspicion that the
$item_list->getFieldDefinition()->getCardinality()
bug is only exposed when mapping multiple times to the same target, so for example:title_en
to Node title with language set to English on the target configuration.title_fr
to Node title with language set to French on the target configuration.My initial testing seems to confirm that suspicion. If so, then I think we need to fix #2994668: Values duplicate when mapping multiple columns to one multi-value text field first in order to add test coverage for this case.
@matthieu_collet, @fbreckx
Can you confirm that you map multiple times to the same target?
Comment #62
shkiper CreditAttribution: shkiper as a volunteer commentedHi @MegaChriz
Is there a reason that 'feeds_item' field type is not translatable?
We have an issue that nodes have the same feed_item value and it get overridden for each translataion import
Comment #63
MegaChriz CreditAttribution: MegaChriz as a volunteer commented@shkiper
The feeds_item field holds a reference to the feed entity and can only hold one reference at a time. So if you use multiple feeds to update the same node, then the feeds_item field get overwritten each time. I haven't diven deeply enough in the multilingual issue in order to answer the question why the feeds_item field is not translatable.
Comment #64
shkiper CreditAttribution: shkiper as a volunteer commentedHi @MegaChriz
Thank you for quick reply :)
Do you know any drawbacks of making this field translatable?
Comment #65
fbreckx CreditAttribution: fbreckx commented@MegaChris, that is correct! Mapping multiple times to same target.
Comment #66
MegaChriz CreditAttribution: MegaChriz as a volunteer commentedI'm working on the tests to expose any bugs the current patch may have.
This patch revamps the test "TranslationTest". Among more, I made the following changes to it:
testClearOutValues()
from the class FeedsMapperMultilingualFieldsTestCase from the D7 version of Feeds.testImportTranslationForExistingNode()
andtestAutocreatedTermLanguage()
from the same D7 class and marked these as incomplete.The tests no longer pass (at least locally).
Next steps are:
No functional changes were made.
Comment #67
fbreckx CreditAttribution: fbreckx commentedHi,
I don't know if it's possible with this patch, but I have a feed that contains all my nodes, for both languages.
When I import this structure now, it ends up importing everything, but is doesn't link translations. It makes a new (untranslated) node per record. NodeID is set to unique, however. Does anyone have a clue on how to link translations?
Comment #68
MegaChriz CreditAttribution: MegaChriz as a volunteer commented@fbreckx
Does mapping source "langcode" to target "Language (langcode)" help? I see that in the source they are in capital letters, I haven't tested yet if that works. If you are already mapping to "Language (langcode)", you could try to convert the source to lowercase with the Feeds Tamper "Convert case" plugin. If you can confirm that lowercase works and uppercase doesn't, it would be a good idea to create a new issue (feature request) to let Feeds accept uppercase language codes.
Comment #69
fbreckx CreditAttribution: fbreckx commented@MegaChriz
I've used lowercase with tamper, didn't mention it. Targeting langcode to language doesn't work. It just creates a new node instead of translating one. I didn't set the language targeting in this scenario.
I will now try to split the feed (one for each language) and create two feeds with language targeting for each field.
UPDATE
Using two feed sources (one per language) and using two feed importers (one per language - with language targeting) doesn't work as well.
Upon importing the second source, the error says: A translation already exists for the specified language (fr).
Comment #70
MegaChriz CreditAttribution: MegaChriz as a volunteer commentedThis ports the tests
testImportTranslationForExistingNode()
andtestAutocreatedTermLanguage()
. They are not passing yet, so unless I made an error in writing these tests, there's serious work to be done to make the patch stable.No functional changes were made.
Comment #71
david.qdoscc CreditAttribution: david.qdoscc commentedI have tried many different combinations of mappings for en and fr sources of a very simple content type (title, one long text field, and unique ref text field).
The most common error I am seeing is the same as reported by @fbrekx: A translation already exists for the specified language (fr).
Please can someone who has had this successfully working provide an explanation of the mappings used, as I must be missing something?
Many thanks,
Comment #72
MegaChriz CreditAttribution: MegaChriz as a volunteer commentedReroll after committing #2994668: Values duplicate when mapping multiple columns to one multi-value text field.
This does remove the changes from
EntityProcessorBase::map()
, because that part is implemented differently in that other issue. By analyzing the code, it looks like the outcome is the same, but I haven't tested that yet. Let's see on the testbot if the amount of test failures is the same.@qdoscc, @fbreckx
Sounds like a new error not covered by the automated tests yet. Does the issue only happen when using two feed types?
Comment #73
fbreckx CreditAttribution: fbreckx commented@MegaChriz: if I use 2 feeds, it doesn't link translations, but it creates 2 separate nodes instead (one per language, without translation).
Comment #74
MegaChriz CreditAttribution: MegaChriz as a volunteer commented@qdoscc, @fbreckx
I'm trying to reproduce the following error:
I tried the following to reproduce the error:
I got values imported for both languages.
Note: when I tried to do a second import I got the following error:
That is something to be fixed still.
Attached the feed types and sources I tested with.
@qdoscc, @fbreckx
Can you provide the exact steps to reproduce the "translation already exists" error?
Comment #75
MegaChriz CreditAttribution: MegaChriz as a volunteer commentedI've created a small spin-off for this issue #3113960: Allow ConfigurableTargetInterface::getSummary() to return an array. It targets point 14 of #49. Since these changes don't depend on the multilingual feature, it is easier to handle it off separately to make future patches for this issue smaller.
As soon as a fix for that issue is committed, I'll create a reroll here. Will probably happen somewhere in the next few days.
Comment #76
MegaChriz CreditAttribution: MegaChriz as a volunteer commentedI committed #3113960: Allow ConfigurableTargetInterface::getSummary() to return an array.
I've been puzzling a bit to get this done right. I'm not done with it yet, but I think it's getting better.
Here's what I've changed:
EntityProcessorBase::map()
- the target mapped to is emptied first. This happened on the entity in the default language. But if on the target a specific language is selected, the target should be emptied in that language instead. So I added a check for langcode and make sure the target on the entity gets emptied in the right language.TranslatableTargetInterface
, to get some of the public methods on FieldTargetBase in an actual interface. This addresses some of the points raised in #49.valuesAreEmpty()
as I yet fail to see why it's needed. And because it should be possible to empty values on the entity (point 8 of #49).FeedType::removeMappings()
(andFeedType::setMappings()
): inFeedType::removeMapping()
something on the property 'targetPlugins' is also emptied, but that didn't happen inFeedType::removeMappings()
. This change should be probably be handled in a spin-off issue.Locally, only
TranslationTest::testAutocreatedTermLanguage()
is failing, but I do expect there's more work to be done in this patch to get things correct. So probably some more automated tests are also needed. I do hope to get this issue done within a few weeks from now (ideally on February 29, but that may be too ambitious), so I may choose to postpone certain refinements.I appreciate it if you want to test this patch on the latest dev, to catch some more bugs. Because the more bugs are catched now, the less likely I may need to make API changes (remove or replace methods) in future releases.
The interdiff isn't an exact interdiff from the patch in #72 as a reroll was also needed because of committing #3113960: Allow ConfigurableTargetInterface::getSummary() to return an array.
Comment #77
MegaChriz CreditAttribution: MegaChriz as a volunteer commentedAdding this as a beta blocker.
Comment #78
toprak CreditAttribution: toprak commentedPatch 76 applied but I can't test if it's worked or not.
Because it doesn't save changes of configure options. (like Autocreate terms(yes/no) or changing language option)
Comment #79
david.qdoscc CreditAttribution: david.qdoscc commented@MegaChriz sorry I've been away from this for a few days. Thanks for your continued work on the issue. I will test this week based on your instructions above and let you know my results.
One thought I had was that in my case I want to import translations of content that already exist on the site (the original language content is not coming from a feed). I am exporting it with views data export to CSV, then the translators will provide a translated CSV for each language. So the question may be how it works in terms of the unique mapping seeing that we cannot select node ID as a unique field (different from D7 where this was possible).
Comment #80
MegaChriz CreditAttribution: MegaChriz as a volunteer commented@toprak
Thanks for reporting. I identified that some changes that I made to FeedType in #76 caused this. I reverted that part for now, although I think it is needed to let
TranslationTest::testMappingFieldsAnotherLanguageImport()
pass.@qdoscc
Great that you want to test the new patch soon! As a workaround, can you use an other field on your content type as unique identifier? Anyway, there's an issue open for mapping to entity ID, though no solutions for it yet: #2989279: Add a target to entity ID
Comment #81
MegaChriz CreditAttribution: MegaChriz as a volunteer commentedLocally, I managed to get all tests from TranslationTest passing! I hope the tests pass on the testbot too.
Here's what I changed:
entityTranslationCheck()
and ensureTranslationLabel(). It seems this code was working around a problem where you don't map to the label of a translation, since the label field is required most of the time. I'm not sure if this should be Feeds responsibility. I figure if Feeds should prepopulate values of a translation, it should not only prepopulate the label, but all values. Because there can exist more required values on the translation.isOwnerFeedAuthor()
andgetOwnerId()
. This was used by FieldTargetBase to prepopulate the author on the translation. Since Feeds does set an author on new entities (if configured), I think it's reasonable if Feeds would do the same for translations. I did move the code doing this fromFieldTargetBase::ensureEntityTranslation()
toEntityProcessorBase::getEntityTranslation()
and put that method right underEntityProcessorBase::newEntity()
, so it's easier to see there's some similarity between these two methods.TranslationTest::testAutocreatedTermLanguage()
pass.TranslationTest::testMappingFieldsAnotherLanguageImport()
andEntityProcessorBaseTest::testMapWithEmptySource()
.This patch could be ready for commit, if it doesn't break tests or introduces new code style issues.
Comment #82
MegaChriz CreditAttribution: MegaChriz as a volunteer commentedGreat, all test pass! Some code style issues still exist though. Fixing these in this patch.
Comment #83
artis.bajars CreditAttribution: artis.bajars commentedDid some testing with the latest patch. After running into the
A translation already exists for the specified language
error already reported here a few times, I followed the mapping setup suggested in #74 which suggests to also map title to the default language. Only then I got the two importers working together.The differences of my setup compared to that example is that I have 2 site languages: English (default) and Finnish, and a translation (EN) may not always exist in the source. This poses a problem, since the first importer (FI) will have already created both EN & FI versions due to that title mapping. Is there any way around this? I've tried mapping variations without the default language title and adding
langcode
mappings but that just leads back to theA translation already exists..
error.Edit: Also, even after the EN importer runs and sets the correct title upon the next run of the FI importer it would just get rewritten which I'm guessing is related to this issue - https://www.drupal.org/project/feeds/issues/3105322.
Comment #84
MegaChriz CreditAttribution: MegaChriz as a volunteer commented@artis.bajars
Thanks for testing! Can you explain the exact steps to reproduce the issues you encounter? I understand you are using two feed types, but I find it hard to parse from your description how these are configured. You mention "langcode". Do you refer in this case to the mapping target "Language" or to the language configured on the mapping target "Title"?
To productively reproduce an issue, I need a numbered list of steps, preferable taken from a clean Drupal install. The list would probably start like this:
And so on.
Comment #85
artis.bajars CreditAttribution: artis.bajars commentedSorry, if my original description was unclear. Here's the steps to follow in my scenario:
Now we have two options:
A: Try to import FI values first. Result - "Import failed. Title (title): This value should not be null."
B: Try to import EN values first, FI after. Result - works as expected, the node has values in both languages.
Additionally I also tried to:
So it appears this only works if the feed that matches the site default language is imported first. In a situation where a source item only exists in the FI data but doesn't have a matching item in the EN source it seems that it's not possible to import it. The only way I was able to import the FI values first was to add another Title mapping to the FI feed type only set to default language. That of course also causes the EN language version of the node to be created and oddly shown as the "Original language" when checking the translations tab. I would kinda expect to be able to create the FI language version as the original without the requiring the EN one.
Comment #86
MegaChriz CreditAttribution: MegaChriz as a volunteer commented@artis.bajars
Thanks for your detailed report! This is useful. I hope to work on it soon.
Comment #87
inst CreditAttribution: inst commentedHi,
I am trying to import terms from a .csv to my vocabulary on my Drupal 8.8.3 site with Feeds 8.x-3.x-dev (2020-Mar-01)
- I prepare a feed type for the terms: name (unique) plus language code for my primary language (german)
- I prepare a feed type for the terms: name (unique) plus language code for my secondary language (english)
- I run the import from my .csv with the names and langcode=de
- I run the import from my .csv with the names and langcode=en
- Finally I get the german and english terms imported.
- But they seem not to be connected - when I click on translate no translation of the term is shown.
Did I miss something or do I take care of special parser settings?
Thanks for any help.
Comment #88
matthieu_collet CreditAttribution: matthieu_collet commentedhi inst
you have to make one .csv file with all the language, and make just one import, each translated field tree times in the import (once per language)
so they will be connected
Comment #89
inst CreditAttribution: inst commentedHi Matthieu,
Ok so my .csv Looks like this:
Column1 Column2
Frankreich France
Italien Italy
How should I configure the Mapping?
And what do you mein with 3 times?
Thanks!
Comment #90
matthieu_collet CreditAttribution: matthieu_collet commentedyou attribute "Column1" to title, in options you choose "German"
you attribut "Column2" to title (also) and you choose "Français" in options
like this screenshot
that's all
Comment #91
inst CreditAttribution: inst commentedThanks again. -
OK I think this way doesn´t works for taxonomy terms.
Here all the fileds I can map. None of them is able to be configured by language.
I attached a screenshot.
Comment #92
matthieu_collet CreditAttribution: matthieu_collet commentedyes you also have this possibility with taxonomy terms
Comment #93
inst CreditAttribution: inst commentedHi,
ouch - I see.
I don´t have this language tab where I can select the language. Strange.
Do you use the latest feeds 8.x-3.x-dev on Drupal 8.8.3 ?
And do I have to use patches on this feeds 8.x-3.x-dev version to make the language tab visible?
merci!
Comment #94
matthieu_collet CreditAttribution: matthieu_collet commentedyes
Drupal core 8.8.3
feeds 8.x-3.x-dev
patch https://www.drupal.org/files/issues/2020-02-27/feeds-content-translation...
Comment #95
matthieu_collet CreditAttribution: matthieu_collet commentedyou didn't patch? did you read this issue ?
Comment #96
inst CreditAttribution: inst commentedGood Morning Matthieu,
ooh - sorry I missed this.
I applied the patch and saw the language select.
It works now - super!!
Thanks again for your help and patience.
Comment #97
MegaChriz CreditAttribution: MegaChriz as a volunteer commentedImport values for non-default language first
This patch allows you to configure the initial language on the processor. This should address case A reported in #85. If you import content in a non-default language, set the language on the processor. This is what the D7 version of Feeds also does.
@artis.bajars
Can you confirm you can import the FI values first with this patch?
A translation already exists for the specified language
I think this does not solve the error "A translation already exists for the specified language". I believe this to be an issue with the language Feeds target. Can everyone that had that error confirm this error only popped up when mapping to "Language (langcode)"?
Since the goal is create a new Feeds release in March, I propose to postpone this issue to a follow-up.
Appreciate anyone who wants to test this patch!
Comment #99
MegaChriz CreditAttribution: MegaChriz as a volunteer commentedUpdating EntityProcessorBaseTest and fixing coding standards.
Comment #100
david.qdoscc CreditAttribution: david.qdoscc commentedThank you very much for your excellent work on this. I have carried out the following test in order to import a French translation of content already existing in the site in the default language (English):
Patches applied:
#99 from this issue
#14 from Use Number fields as unique mapping target
#9 from Add a target to entity ID
Feed configured:
Upload file of CSV to Node processor.
Processor settings: Language French, Update existing contents
Source (CSV column) -> Mapping Target:
nid -> ID (nid) *Unique
title_fr -> Title (title) *Language: French
alias -> URL alias (path) *Language: French
my_field -> My Field (field_my_field) *Language: French
Results:
- French translations of nodes are created correctly without any errors
- Title and my_field are populated as expected
- Alias is not set (but I expected this as feeds showed it as Read only on the mapping... is there another way?)
Conclusion:
It works really well for my purposes! For now I will use URL alias patterns as a workaround for not being able to import the aliases.
Note:
As I was working on an existing installation with feeds already set up, I found it necessary to do things in the following order:
If I did not do the uninstall/reinstall then I encountered an error such as:
Drupal\Core\Database\DatabaseExceptionWrapper: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'mysite_sql.feeds_clean_list' doesn't exist: DELETE FROM {feeds_clean_list} WHERE feed_id IN (:db_condition_placeholder_0); Array ( [:db_condition_placeholder_0] => 14 ) in Drupal\feeds\Entity\Feed::postDelete() (line 556 of /home/mysite/drupal/web/modules/feeds/src/Entity/Feed.php).
Comment #101
MegaChriz CreditAttribution: MegaChriz as a volunteer commented@qdoscc
Thanks a lot for testing!
#2989279: Add a target to entity ID exposes read only fields. I wasn't aware that it would also expose path alias as read only field. Read only fields can only be set once as else that causes issues for entity ID. Sounds like that needs more refinement. But you can import aliases with a separate feed type, using the URL alias processor (I hope, did not test that myself). Since D8.8 a path alias became a separate entity type in Drupal core, thus as a result you could no longer import it in one go with nodes.
Did you run database updates after updating to the latest dev? Because
feeds_update_8002()
is supposed to add that table when it doesn't exist yet. If you remember that you did run database updates then there might be an issue with that update function.Comment #102
david.qdoscc CreditAttribution: david.qdoscc commentedNo I didn't! That makes sense then :)
Comment #103
MegaChriz CreditAttribution: MegaChriz as a volunteer commentedI noticed that for some mappers on the mapping form a wheel icon appeared, but when clicking it you got an empty form.
This is for example the case for the feeds item target for which no language selector is available:
The reason is that now all field targets have become "configurable", because of implementing ConfigurableTargetInterface.
So I checked core's EntityDisplayFormBase to see how that handles configurable items and it appears that it's checking for each plugin if the settings form method is returning something:
Feeds did only check if a plugin implemented ConfigurableTargetInterface. I now applied similar logic as above to determine if a wheel icon should be displayed for a target.
In comparison of the patch in #99, this patch only introduces changes on the mapping form. There are no changes for the multilingual import functionality.
Comment #104
MegaChriz CreditAttribution: MegaChriz as a volunteer commentedI noticed the following error on the mapping page when mapping to an entity reference field:
The reason is that Feeds now calls
buildConfigurationForm()
when no target settings are open, so the following code does not result in$delta
being set.Fixed the notice by setting
$delta
to0
.There are no changes for the multilingual import functionality.
Comment #105
matthieu_collet CreditAttribution: matthieu_collet commentedHi MegaChriz
on which version of feeds exactly did you apply the patch ?
with 3.0.0-alpha6 I have the composer error :
Could not apply patch! Skipping. The error was: Cannot apply patch https://www.drupal.org/files/issues/2020-03-25/feeds-content-translation-2829283-104.patch
without any details
thank you
matthieu
Comment #106
MegaChriz CreditAttribution: MegaChriz as a volunteer commented@matthieu
The patch is created for the latest dev version, so it doesn’t apply on alpha6. I hope to release alpha7 soon and I hope this could be part of the new release. In the next few days I decide whether this is good enough for commit.
Comment #107
matthieu_collet CreditAttribution: matthieu_collet commentedthank you!
problem was there, it works now
Comment #108
MegaChriz CreditAttribution: MegaChriz as a volunteer commentedMinor code cleanup. No functional changes are made.
Comment #110
MegaChriz CreditAttribution: MegaChriz as a volunteer commentedGood. Tests still passing :)
Committed #108! Thanks everyone.
I created a follow-up issue for fixing the "A translation already exists for the specified language" error:
#3126351: A translation already exists for the specified language
Comment #112
mazze CreditAttribution: mazze commentedThank you Megachriz, this thread saved my day:-)
Comment #113
trickfun CreditAttribution: trickfun commentedHi,
Translation works fine but only default language path alias is created.
I have product in 3 languages. italian is default language.
After import i have only path alias of italian product.
All path alias are set with patterns, one for language.
Thank you