├── LICENSE ├── README.md ├── config └── install │ ├── block.block.languageswitcher.yml │ ├── core.entity_form_display.node.element.default.yml │ ├── core.entity_view_display.node.element.default.yml │ ├── core.entity_view_display.node.element.teaser.yml │ ├── field.field.node.article.field_one_liner.yml │ ├── field.field.node.element.body.yml │ ├── field.field.node.element.field_element_discoverer.yml │ ├── field.field.node.element.field_element_symbol.yml │ ├── field.storage.node.field_element_discoverer.yml │ ├── field.storage.node.field_element_symbol.yml │ ├── field.storage.node.field_one_liner.yml │ ├── language.content_settings.node.article.yml │ ├── language.content_settings.node.element.yml │ ├── language.entity.es.yml │ ├── language.entity.fr.yml │ ├── migrate_plus.migration.example_creature_base.yml │ ├── migrate_plus.migration.example_creature_i18n.yml │ ├── migrate_plus.migration.example_dog_base.yml │ ├── migrate_plus.migration.example_dog_i18n.yml │ ├── migrate_plus.migration.example_element_en.yml │ ├── migrate_plus.migration.example_element_es.yml │ ├── migrate_plus.migration.example_hybrid_base.yml │ ├── migrate_plus.migration.example_hybrid_i18n.yml │ ├── migrate_plus.migration_group.example_creature.yml │ ├── migrate_plus.migration_group.example_dog.yml │ ├── migrate_plus.migration_group.example_element.yml │ ├── migrate_plus.migration_group.example_hybrid.yml │ ├── node.type.element.yml │ └── views.view.elements.yml ├── dump ├── Makefile ├── sandbox_d6.sql ├── sandbox_d7_content.sql ├── sandbox_d7_entity.sql └── settings.local.php ├── import ├── README.md └── element │ ├── element.data.en.csv │ └── element.data.es.csv ├── migrate_example_i18n.info.yml ├── migrate_example_i18n.install ├── migrate_example_i18n.module └── src └── Plugin └── migrate └── source ├── D7NodeContentTranslation.php └── D7NodeEntityTranslation.php /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Drupal 8 I18N / Translation Migration Example 2 | 3 | Although a majority of sites only offer their content in one language, there are many which offer all or some of their content in two or more languages. When a multi-language site decides to migrate to Drupal 8, one of the major concerns is migrating the content whilst preserving the translations. Luckily, Drupal 8 has a very straight forward and standardized framework for supporting translations, unlike its predecessors. 4 | 5 | In this project, we would briefly discuss how to migrate translated content into Drupal 8. More specifically, we would see how to migrate the following items into Drupal 8: 6 | 7 | * Drupal 6 content - translated with the 'content_translation' module. 8 | * Drupal 7 content - translated with the 'content_translation' module. 9 | * Drupal 7 content - translated with the 'entity_translation' module. 10 | * Non-drupal content - CSV files containing base data and translations. 11 | 12 | # Quick start 13 | 14 | * Put this module in your Drupal installation: 15 | 16 | ```git clone https://github.com/evolvingweb/migrate_example_i18n.git modules/custom/migrate_example_i18n``` 17 | 18 | * Install the module. 19 | 20 | ```drush en migrate_example_i18n -y``` 21 | 22 | * Configure Drupal to talk to a secondary database. For the Drupal 6 example, you can add something like this to your `settings.php`: 23 | 24 | ``` 25 | $databases['drupal_6']['default'] = array( 26 | 'database' => 'migrate_i18n_d6', 27 | 'driver' => 'mysql', 28 | 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql', 29 | 'username' => 'root', 30 | 'password' => 'f00b@r', 31 | 'host' => '127.0.01', 32 | ); 33 | ``` 34 | 35 | Don't forget to modify the username, password and host! 36 | 37 | You can add similar stanzas for the D7 examples, see [settings.local.php](dump/settings.local.php). 38 | 39 | * Create and populate your new source databases. Eg, for Drupal 6: 40 | 41 | ``` 42 | drush sql-create --database=drupal_6 --yes 43 | drush sql-cli --database=drupal_6 < modules/custom/migrate_example_i18n/dump/sandbox_d6.sql 44 | ``` 45 | 46 | Again, you can do something similar for D7. 47 | 48 | * Check the current status of the migrations. 49 | 50 | ```drush migrate-status``` 51 | 52 | * Run some migrations introduced by this module. Eg, for Drupal 6: 53 | 54 | ```drush migrate-import --group=example_hybrid --update``` 55 | 56 | # The problem 57 | 58 | We have 4 sets of data from various sources which we have to migrate into Drupal 8: 59 | 60 | * **Drupal 6 - Content Translation:** A bunch of _story_ nodes about hybrid animals need to be migrated to Drupal 8. These have been handled in the `config/install/migrate_plus.migration.example_hybrid_*.yml` files. 61 | * **Drupal 7 - Content Translation:** A bunch of _article_ nodes about dogs need to be migrated to Drupal 8. These have been handled in the `config/install/migrate_plus.migration.example_dog_*.yml` files. 62 | * **Drupal 7 - Entity Translation:** A bunch of _article_ nodes about mythological creatures need to be migrated to Drupal 8. These have been handled in the `config/install/migrate_plus.migration.example_creature_*.yml` files. 63 | * **Non-drupal source:** A table of chemical elements is provided in 2 different files - one in English and the other in Spanish. We need to migrate the contents of these two files and create nodes having translations in English and Spanish. These have been handled in the `config/install/migrate_plus.migration.example_element_*.yml` files. 64 | 65 | # Assumptions 66 | 67 | Since this is an advanced migration topic, it is assumed that you already have the following knowledge: 68 | 69 | * How to create a custom module in Drupal 8 70 | * How to write a basic migration in Drupal 8 71 | * How to install and use [drush](http://www.drush.org/) commands 72 | * How to configure a multi-linguage website on Drupal 8 73 | 74 | # The module 75 | 76 | There is nothing special about the module definition as such, however, here are certain things which need a mention: 77 | 78 | * In Drupal 8, unlike Drupal 7, a module only provides a .module file only if required. In our example, we use that file to define some hooks which are required to make this module work correctly. 79 | * Though the migrate module is in Drupal 8 core, we need most of these dependencies to enable / enhance migrations on the site: 80 | * [migrate_plus](https://www.drupal.org/project/migrate_plus): To make our life easy 81 | * [migrate_tools](https://www.drupal.org/project/migrate_tools): To make our life easy 82 | * [migrate_source_csv](https://www.drupal.org/project/migrate_source_csv): To use CSV files as migration data sources. 83 | * migrate_drupal: We need this module to use Drupal 6 and Drupal 7 sites as data sources for our migration. This module is a part of the Drupal 8.x core. 84 | 85 | # Drupal 8 configuration 86 | 87 | Before migrating translated content into Drupal 8, one must make sure that their Druapl 8 site actually supports translated content. To do this, we need to: 88 | 89 | * Enable the `language` module and set up languages and method of language determination. Example: Set up English and French. 90 | * Enable the `content_translation` module. 91 | * Configure the content types which you want to be translatable. Example, edit the _Article_ content type and enable translations. 92 | * Make sure you have your content types and fields configured as per the data you wish to import. Example, if your source articles have a field named _One-liner_, make sure the Drupal 8 nodes have a corresponding field to save the data in. 93 | 94 | # Migrate hybrids: Drupal 6 content translations to Drupal 8 95 | 96 | Since Drupal 6 is older, it looks like a better place to start. To get started, we create a migration group named [example_hybrid](config/install/migrate_plus.migration_group.example_hybrid.yml). This would let us execute all grouped migrations with one command like 97 | 98 | drush migrate-import --group=example_hybrid --update 99 | 100 | Migrating translated content into Drupal 8 usually involves two steps: 101 | 102 | * Base migration: Migrate data in base language and ignore translations. 103 | * Translation migration: Migrate only the translations (and ignore data in base language). These translations are usually linked to the content we create in the first step, thereby leaving us with only one entity with multiple translations. 104 | 105 | Before jumping into writing these migrations, it is important to mention that Drupal 6 and Drupal 8 translations work very differently. Here's the difference in a nutshell: 106 | 107 | * **Drupal 6:** First, you create a piece of content in its base language. Then, you add a translation of it. However, when you create a translation, another fresh node is created with a different ID and a property named `tnid` is used to save the ID of the original node, thereby recording the fact that the node is a translation of another node. For language-neutral content the `tnid` is set to 0. 108 | * **Drupal 8:** First, you create a piece of content in its base language. Then, you add a translation of it. When you create the translation, no new node is created. The translation is saved against the original node itself but measures are taken to save the translations in the other language. 109 | 110 | Hence we follow the two step process for migrating translated content from Drupal 6. 111 | 112 | ## Hybrid base migration 113 | 114 | Having created the migration group, we would create our first migration with the ID [example_hybrid_base](config/install/migrate_plus.migration.example_hybrid_base.yml). We do this by defining some usual parameters: 115 | 116 | * **id:** An unique ID for the migration. 117 | * **migration_group:** The group to which the migration belongs. 118 | * **migration_tags:** A set of tags for the migration. 119 | * **source:** 120 | * **plugin:** Since we want to import data from a Drupal installation, we need to set the source plugin to `d6_node`. The `d6_node` source plugin is introduced by the `migrate_drupal` module and it helps us read nodes from a Drupal 6 installation without having to manually write queries to read the nodes and attaching the relevant fields, etc. 121 | * **node_type:** With this parameter we tell the source plugin that we are interested in reading a particular node type only, in this case, _story_. 122 | * **key:** Since we intend to read the Drupal 6 data from a secondary database connection (the primary one being the Drupal 8 database), we need to define the secondary connection in the `$databases` global variable in our `settings.local.php` file. Once done, we need to mention the `key` of the `$databases` array where the Drupal 6 connection is defined. 123 | * **target:** Optionally, you can also define a _target_. This parameter defaults to `default` and should be defined if your connection is not defined in the `default` sub-key of `$databases`. But usually this parametre is left as `default`, so we can safely omit it. 124 | * **constants:** We define some static / hard-coded values under this parameter. 125 | * **translations:** We DO NOT define the translations parameter while migrating base data. Omiting the parameter or setting it to `false` tells the source plugin that we are only interested in migrating non-translations, i.e. content in base language and language-neutral content. It is important NOT to specify this parameter otherwise you will end up with separate nodes for every language variation of each node. 126 | * **destination:** 127 | * **plugin:** Since we want to create node entities, we specify this as `entity:node`. That's it. 128 | * **translations:** We DO NOT define the translations parameter while migrating base data. Omiting the parameter or setting it to `false` tells the destination plugin that we are interested in creating fresh nodes for each record as opposed to associating them as translations for existing nodes. 129 | * **process:** This is where we tell migrate how to map the old node properties to the new node properties. Most of the properties have been assigned as is, without alteration, however, some noteworthy properties have been discussed below: 130 | * **type:** We use a constant value to define the type of nodes we wish to create from the imported data. 131 | * **langcode:** The `langcode` parameter was formerly `language` in Drupal 6. So we need to assign it properly so that Drupal 8 knows as to in which language the node is to be created. We use the `default_value` plugin here to provide a fallback to the `und` or `undefined` language just in case some node is out of place, however, it is highly unlikely that it happens. 132 | * **body:** We can assign this property directly to the `body` property. However, the Drupal 6 data is treated as plain text in Drupal 8 in that case. So migrating with `body: body`, the imported nodes in Drupal 8 would show visible HTML markup on your site. To resolve this, we explicitly assign the old `body` to `body/value` and specify that the text is in HTML by writing `body/format: constants/body_format`. That tells Drupal to treat the body as _Full HTML_. 133 | 134 | This takes care of the base data. If you run this migration with `drush migrate-import example_hybrid_i18n --update`, all Drupal 6 nodes which are in base language or are language-neutral will be migrated into Drupal 8. 135 | 136 | ## Hybrid translation migration 137 | 138 | We are halfway through now and all that's missing is migrating translations of the nodes we migrated above. To do this, we create another migration with the ID [example_hybrid_i18n](config/install/migrate_plus.migration.example_hybrid_i18n.yml). The migration definition remains mostly the same but has the following important differences as compared to the base migration: 139 | 140 | * **source:** 141 | * **translations:** We define this parameter to make the source plugin read only translation nodes and to make it ignore the nodes we already migrated in the base migration. 142 | * **destination:** 143 | * **translations:** We define this parameter to make the destination plugin create translations for existing nodes instead of creating fresh nodes for each source record. 144 | * **process:** 145 | * **nid:** Are we defining an ID for the nodes to be generated? Yes, we are. With the `nid` parameter, we use the `migration` plugin and tell Drupal to create translations for the nodes we created during the base migration, like `plugin: migration` and `migration: example_hybrid_base`. So, for every record, Drupal derives the ID of the relevant node created during the base migration and creates a translation for it. 146 | * **langcode:** This is important because here we define the language in which the translation should be created. 147 | * **migration_dependencies:** Since we cannot associate the translations to the base nodes if the base nodes do not exist, we tell Drupal that this migration depends on the base migration `example_hybrid_base`. That way, one will be forced to run the base migration before running this migration. 148 | 149 | That's it! We can run our translation migration with `drush migrate-import example_hybrid_i18n --update` and the translations will be imported into Drupal 8. You can check if everything went alright by clicking the `Translate` option for any translated node in Drupal 8. If everything went correctly, you should see that the node exists in the original language and has one or more translations. 150 | 151 | # Migrate dogs: Drupal 7 content translations to Drupal 8 152 | 153 | Great! So another set of content translations! The good news is that content translations work the same way in Drupal 7 as they do in Drupal 6. Drupal 8.3.x and higher support D7 content translations out of the box. For older D8 versions, we can support the `translations` parameter with a custom source plugin like [D7NodeContentTranslation](src/Plugin/migrate/src/D7NodeContentTranslation.php). Here's a quick introduction to the class: 154 | 155 | * The class is derived from `\Drupal\node\Plugin\migrate\source\d7\Node` which would eventually support the `translations` parameter and make our lives easier. 156 | * The annotation `@MigrateSource` makes it available as a migration source plugin. The plugin ID being `d7_node_content_translation`. 157 | * The `query` method has been overridden to intercept the query used by the migration module to read source records. We call a `handleTranslations` method on the query which does what it's name says, handles translations. 158 | * The `handleTranslations` method is an exact copy of the one which exists in the Drupal 6 node source plugin. It adds support for the `tranlsations` parameter: 159 | * If `translations: true`, then it modifies the query so that it would only return translated nodes. 160 | * If `translations: false`, then it modifies the query so that it would only return non-translations, i.e. nodes in base language and language-neutral nodes. 161 | 162 | Apart from that, we have everything going just the way we did for Drupal 6. 163 | 164 | ## Dog base migration 165 | 166 | We define a [example_dog_base](config/install/migrate_plus.migration.example_dog_base.yml) migration to migrate all non-translations first. 167 | 168 | * We use our `d7_node_content_translation` plugin as the `source` plugin. 169 | * We do not declare `translations` parameter for the `source` plugin, so that only non-translations are read from Drupal 7. 170 | * We do not declare `translations` parameter for the `destination` plugin. Thus, separate Drupal 8 nodes will be generated for every Drupal 7 node. 171 | 172 | ## Dog translation migration 173 | 174 | We define a [example_dog_i18n](config/install/migrate_plus.migration.example_dog_i18n.yml) migration to migrate all translations. 175 | 176 | * We use our `d7_node_content_translation` plugin as the `source` plugin. 177 | * We define `translations: true` for the source plugin so that only translated nodes are read from Drupal 7 178 | * We define `translations: true` for the destination plugin so that the data is migrated as translations for nodes created during the base migration. 179 | * We make sure that the `i18n` migration depends on the `base` migration. 180 | 181 | That's it! We can run the base and i18n migrations one by one and all Drupal 7 nodes would be imported to Drupal 8 along with their translations. To execute both the migrations at once, we can run the command `drush migrate-import --group=example_dog --update`. Perfect! 182 | 183 | # Migrate creatures: Drupal 7 entity translations to Drupal 8 184 | 185 | Entity translations! Amazing! Drupal 7 content translations are supported since Drupal 8.3. At the point of writing this, there is no standard method for migrating entity translations to Drupal 8. In this example, we will migrate D7 nodes translated with the [entity_translation](https://www.drupal.org/project/entity_translation) module. The procedure should be similar for other node types as well. Before we start, here are some notes about what's so different about entity translations: 186 | 187 | * All translations have the same `entity_id`. So, for a translated node, the entity_translation module will result in only one entry in the `node` table. 188 | * Translation information and revisions for entities is stored in the `entity_translation` table. So if an English node with ID 19 has translations in Spanish and French, the `entity_translations` table has the following records: 189 | * `entity_type: node; entity_id: 19; language: en; ...` 190 | * `entity_type: node; entity_id: 19; language: es; ...` 191 | * `entity_type: node; entity_id: 19; language: fr; ...` 192 | 193 | The above data structure is significantly different from the content translation structure. In fact, Drupal 8 handles translations much like the entity translation module! 194 | 195 | ## class D7NodeEntityTranslation 196 | 197 | To migrate entity translations, we must make significant number of changes to the migration source (at least at the time of writing this). We need to migrate Drupal 7 nodes, so we extend the `d7_node` migration source. 198 | 199 | class D7NodeEntityTranslation extends D7Node { 200 | // Determines if the node-type being translated supports entity_translation. 201 | protected function isEntityTranslatable() {} 202 | // Depending on the "source/translations" parameter, this method alters 203 | // the migration query to return only translations or non-translations. 204 | protected function handleTranslations(SelectInterface $query) {} 205 | // This method has been overridden to ensure that every node's fields are 206 | // are loaded in the correct language. 207 | public function prepareRow(Row $row) {} 208 | // This method is called by the prepareRow() method to load field values 209 | // for source nodes. We override this method to add support for $language. 210 | protected function getFieldValues($entity_type, $field, $entity_id, $revision_id = NULL, $language = NULL) {} 211 | // Since all source nodes have the same "nid", we need to use a 212 | // combination of "nid:language" to distinguish each source translation. 213 | public function getIds() {} 214 | } 215 | 216 | With the above source class in place, we write our migrations as usual. 217 | 218 | ## Creature base migration 219 | 220 | We define a [example_creature_base](config/install/migrate_plus.migration.example_creature_base.yml) migration to migrate all non-translations first. 221 | 222 | * We use our `d7_node_entity_translation` plugin as the `source` plugin to handle entity translations correctly. 223 | * We do not declare `translations` parameter for the `source` plugin, so that only non-translations are read from Drupal 7. 224 | * We do not declare `translations` parameter for the `destination` plugin. Thus, separate Drupal 8 nodes will be generated for every Drupal 7 node. 225 | 226 | ## Creature translation migration 227 | 228 | We define a [example_creature_i18n](config/install/migrate_plus.migration.example_creature_i18n.yml) migration to migrate all translations. 229 | 230 | * We use our `d7_node_entity_translation` plugin as the `source` plugin to handle entity translations correctly. 231 | * We define `translations: true` for the source plugin so that only translated nodes are read from Drupal 7 232 | * We define `translations: true` for the destination plugin so that the data is migrated as translations for nodes created during the base migration. 233 | * We make sure that the `i18n` migration depends on the `base` migration. 234 | 235 | That's it! We can run the base and i18n migrations one by one and all Drupal 7 nodes would be imported to Drupal 8 along with their translations. To execute both the migrations at once, we can run the command `drush migrate-import --group=example_creature --update`. Perfect! 236 | 237 | # Migrate elements: Non-drupal translated content to Drupal 8 238 | 239 | As we do with any other translated content migration, we will follow the same old two steps here: 240 | 241 | * Migrate the content in base language. In our case, this is English (en). 242 | * Migrate the content in Spanish (es) such that they are saved as translations for the English content. 243 | 244 | ## Element base migration (English) 245 | 246 | To achieve this, we define the [example_element_en](config/install/migrate_plus.migration.example_element_en.yml) migration to migrate element data in base language, which in our case is English (en). Here is a quick look at some important parameters used in the migration definition: 247 | 248 | * **source:** 249 | * **plugin:** Since we want to import data from a CSV file, we need to use the _csv_ plugin provided by the [migrate_source_csv](https://www.drupal.org/project/migrate_source_csv) module. 250 | * **path:** Path to the CSV data source so that the source plugin can read the file. 251 | * **header_row_count:** Number of initial rows in the CSV file which do not contain actual data. This helps ignore column headings. 252 | * **keys:** The column or columns in the CSV file which help uniquely identify each record. In our example, the chemical symbol in the column _Symbol_ is unique to each row, hence, we use that as the key. 253 | * **fields:** A description for every column present in the CSV file. This is used for displaying source details in the UI. 254 | * **constants:** Some static values for use during the migration. 255 | * **destination:** 256 | * **plugin:** Nothing fancy here. We aim to create _node_ entities, so we set the `plugin` as `entity:node`. 257 | * **translations:** Since we are importing the content in base language, we do not specify the `translations` parameter. This will make Drupal create individual nodes for every record. 258 | * **process:** Most of the properties are migrated as is. However, here are some of them which need a special explication: 259 | * **type:** We hard-code the type of nodes we wish to create, i.e., `type: constants/node_element`. 260 | * **langcode:** Since all source records are in English, we inform Drupal to save the destination nodes in English as well. We do this by explicitly specifying `langcode` as `en`. 261 | * **field_element_discoverer:** This field is a bit tricky. Looking at the source, we realize that every element has one or more discoverers. Multiple discoverer names are separated by commas. Thus, we use `plugin: explode` and `delimiter: ', '` to split multiple records into arrays. With the values split into arrays, Drupal understands and saves the column data as multiple values. 262 | 263 | After we run this migration like `drush migrate-import example_element_en`, we get a list of all elements in the base language (English). 264 | 265 | ## Element translation migration (Spanish) 266 | 267 | With the base nodes in place, we define a similar migration to the previous one with the ID [example_element_es](config/install/migrate_plus.migration.example_element_es.yml). Let us look at some major differences between the `example_element_es` migration and the `example_element_en` migration: 268 | 269 | * **source:** 270 | * **path:** Since the Spanish node data is in another file, we change the path accordingly. 271 | * **keys:** The Spanish word for _Symbol_ is _Símbolo_ and it is the column containing the unique ID of each record. Hence, we define it as the source data key. A noteworthy observation here would be the special `í` in the word `Símbolo`. Since it is a special character, setting it as a `key` did not work. So, as a workaround, I had to remove all such accented characters from the column headings and write the `key` parameter as `Simbolo` without the special `í` with a normal `i`. 272 | * **fields:** The field definitions had to be changed to match the Spanish column names used in the CSV. 273 | * **destination:** 274 | * **translations:** Since we want Drupal to create translations for English language nodes created during the `example_element_en` migration, we specify `translations: true`. 275 | * **process:** 276 | * **nid:** As mentioned above, we use the `plugin: migration` to make Drupal lookup nodes which were created during the English element migration and use their ID as the `nid`. This results in the Spanish translations being attached to the original nodes created in English. 277 | * **langcode:** Since all records in [element.data.es.csv](import/element/element.data.es.csv) are in Spanish, we hard-code the `langcode` to `es` for each record of this migration. This tell Drupal that these are _Spanish_ translations. 278 | * **migration_dependencies:** This ensures that the base data is migrated before the translations. So to run this migration, one must run the `example_element_en` migration first. 279 | 280 | Voilà! Run the Spanish migration like `drush migrate-import example_element_es` and you have the Spanish translations for the elements! If we had another file containing French translations, we would create another migration like we did for Spanish and import the French data in a similar way. I could not find a CSV with element data in French, so I could not include it in this example :( 281 | 282 | # Things to remember 283 | 284 | * We migrate the base data first! No need for setting any `translations` parameters here. 285 | * We migrate the translations after the base data. We need to set `translations: true` for the `destination` plugin. We might have to set `translations: true` for the source plugin depending on the source we are using. 286 | * We must ensure that the correct `langcode` is being set for the destination nodes. 287 | * We must ensure that the translation migration depends on the base migration. We do this using the `migration_dependencies` parameter. 288 | -------------------------------------------------------------------------------- /config/install/block.block.languageswitcher.yml: -------------------------------------------------------------------------------- 1 | uuid: 4689844e-8fae-4f9f-83f0-470edf077233 2 | langcode: es 3 | status: true 4 | dependencies: 5 | module: 6 | - language 7 | theme: 8 | - bartik 9 | id: languageswitcher 10 | theme: bartik 11 | region: header 12 | weight: -5 13 | provider: null 14 | plugin: 'language_block:language_interface' 15 | settings: 16 | id: 'language_block:language_interface' 17 | label: 'Language switcher' 18 | provider: language 19 | label_display: '0' 20 | visibility: { } 21 | -------------------------------------------------------------------------------- /config/install/core.entity_form_display.node.element.default.yml: -------------------------------------------------------------------------------- 1 | uuid: 045fe1c6-750b-4f44-a22a-02c93f8497d0 2 | langcode: en 3 | status: true 4 | dependencies: 5 | config: 6 | - field.field.node.element.body 7 | - field.field.node.element.field_element_discoverer 8 | - field.field.node.element.field_element_symbol 9 | - node.type.element 10 | module: 11 | - path 12 | - text 13 | id: node.element.default 14 | targetEntityType: node 15 | bundle: element 16 | mode: default 17 | content: 18 | body: 19 | type: text_textarea_with_summary 20 | weight: 3 21 | settings: 22 | rows: 9 23 | summary_rows: 3 24 | placeholder: '' 25 | third_party_settings: { } 26 | created: 27 | type: datetime_timestamp 28 | weight: 6 29 | settings: { } 30 | third_party_settings: { } 31 | field_element_discoverer: 32 | weight: 4 33 | settings: 34 | size: 60 35 | placeholder: '' 36 | third_party_settings: { } 37 | type: string_textfield 38 | field_element_symbol: 39 | weight: 2 40 | settings: 41 | size: 60 42 | placeholder: '' 43 | third_party_settings: { } 44 | type: string_textfield 45 | langcode: 46 | type: language_select 47 | weight: 1 48 | settings: { } 49 | third_party_settings: { } 50 | path: 51 | type: path 52 | weight: 10 53 | settings: { } 54 | third_party_settings: { } 55 | promote: 56 | type: boolean_checkbox 57 | settings: 58 | display_label: true 59 | weight: 8 60 | third_party_settings: { } 61 | sticky: 62 | type: boolean_checkbox 63 | settings: 64 | display_label: true 65 | weight: 9 66 | third_party_settings: { } 67 | title: 68 | type: string_textfield 69 | weight: 0 70 | settings: 71 | size: 60 72 | placeholder: '' 73 | third_party_settings: { } 74 | translation: 75 | weight: 7 76 | settings: { } 77 | third_party_settings: { } 78 | uid: 79 | type: entity_reference_autocomplete 80 | weight: 5 81 | settings: 82 | match_operator: CONTAINS 83 | size: 60 84 | placeholder: '' 85 | third_party_settings: { } 86 | hidden: { } 87 | -------------------------------------------------------------------------------- /config/install/core.entity_view_display.node.element.default.yml: -------------------------------------------------------------------------------- 1 | uuid: 7b157724-0715-415b-99f3-2d4409e902d1 2 | langcode: en 3 | status: true 4 | dependencies: 5 | config: 6 | - field.field.node.element.body 7 | - field.field.node.element.field_element_discoverer 8 | - field.field.node.element.field_element_symbol 9 | - node.type.element 10 | module: 11 | - text 12 | - user 13 | id: node.element.default 14 | targetEntityType: node 15 | bundle: element 16 | mode: default 17 | content: 18 | body: 19 | label: hidden 20 | type: text_default 21 | weight: 2 22 | settings: { } 23 | third_party_settings: { } 24 | field_element_discoverer: 25 | weight: 1 26 | label: inline 27 | settings: 28 | link_to_entity: false 29 | third_party_settings: { } 30 | type: string 31 | field_element_symbol: 32 | weight: 0 33 | label: inline 34 | settings: 35 | link_to_entity: false 36 | third_party_settings: { } 37 | type: string 38 | hidden: 39 | langcode: true 40 | links: true 41 | -------------------------------------------------------------------------------- /config/install/core.entity_view_display.node.element.teaser.yml: -------------------------------------------------------------------------------- 1 | uuid: 4eaec770-0f15-4c6a-8c49-1a3f1820f9af 2 | langcode: en 3 | status: true 4 | dependencies: 5 | config: 6 | - core.entity_view_mode.node.teaser 7 | - field.field.node.element.body 8 | - field.field.node.element.field_element_discoverer 9 | - field.field.node.element.field_element_symbol 10 | - node.type.element 11 | module: 12 | - text 13 | - user 14 | id: node.element.teaser 15 | targetEntityType: node 16 | bundle: element 17 | mode: teaser 18 | content: 19 | body: 20 | label: hidden 21 | type: text_summary_or_trimmed 22 | weight: 1 23 | settings: 24 | trim_length: 600 25 | third_party_settings: { } 26 | field_element_symbol: 27 | type: string 28 | weight: 0 29 | label: inline 30 | settings: 31 | link_to_entity: false 32 | third_party_settings: { } 33 | links: 34 | weight: 2 35 | settings: { } 36 | third_party_settings: { } 37 | hidden: 38 | field_element_discoverer: true 39 | langcode: true 40 | -------------------------------------------------------------------------------- /config/install/field.field.node.article.field_one_liner.yml: -------------------------------------------------------------------------------- 1 | uuid: 34ef216e-184a-4ea1-8f13-d2ac532190cb 2 | langcode: en 3 | status: true 4 | dependencies: 5 | config: 6 | - field.storage.node.field_one_liner 7 | - node.type.article 8 | id: node.article.field_one_liner 9 | field_name: field_one_liner 10 | entity_type: node 11 | bundle: article 12 | label: One-liner 13 | description: '' 14 | required: false 15 | translatable: true 16 | default_value: { } 17 | default_value_callback: '' 18 | settings: { } 19 | field_type: string 20 | -------------------------------------------------------------------------------- /config/install/field.field.node.element.body.yml: -------------------------------------------------------------------------------- 1 | uuid: a6c2e468-93b1-499f-b4a0-afeec3b680b3 2 | langcode: en 3 | status: true 4 | dependencies: 5 | config: 6 | - field.storage.node.body 7 | - node.type.element 8 | module: 9 | - text 10 | id: node.element.body 11 | field_name: body 12 | entity_type: node 13 | bundle: element 14 | label: Body 15 | description: '' 16 | required: false 17 | translatable: true 18 | default_value: { } 19 | default_value_callback: '' 20 | settings: 21 | display_summary: true 22 | field_type: text_with_summary 23 | -------------------------------------------------------------------------------- /config/install/field.field.node.element.field_element_discoverer.yml: -------------------------------------------------------------------------------- 1 | uuid: d87e4085-2ad7-4919-9328-e490ecf37879 2 | langcode: en 3 | status: true 4 | dependencies: 5 | config: 6 | - field.storage.node.field_element_discoverer 7 | - node.type.element 8 | id: node.element.field_element_discoverer 9 | field_name: field_element_discoverer 10 | entity_type: node 11 | bundle: element 12 | label: Discoverers 13 | description: 'Names of scientists who discovered the element.' 14 | required: false 15 | translatable: false 16 | default_value: { } 17 | default_value_callback: '' 18 | settings: { } 19 | field_type: string 20 | -------------------------------------------------------------------------------- /config/install/field.field.node.element.field_element_symbol.yml: -------------------------------------------------------------------------------- 1 | uuid: 33dfb14a-2377-4dfa-993c-c7a72620dacc 2 | langcode: en 3 | status: true 4 | dependencies: 5 | config: 6 | - field.storage.node.field_element_symbol 7 | - node.type.element 8 | id: node.element.field_element_symbol 9 | field_name: field_element_symbol 10 | entity_type: node 11 | bundle: element 12 | label: Symbol 13 | description: 'The unique chemical symbol for the element.' 14 | required: true 15 | translatable: false 16 | default_value: { } 17 | default_value_callback: '' 18 | settings: { } 19 | field_type: string 20 | -------------------------------------------------------------------------------- /config/install/field.storage.node.field_element_discoverer.yml: -------------------------------------------------------------------------------- 1 | uuid: ccfc20d5-44cc-4c17-acb0-67248aae1b43 2 | langcode: en 3 | status: true 4 | dependencies: 5 | module: 6 | - node 7 | id: node.field_element_discoverer 8 | field_name: field_element_discoverer 9 | entity_type: node 10 | type: string 11 | settings: 12 | max_length: 255 13 | is_ascii: false 14 | case_sensitive: false 15 | module: core 16 | locked: false 17 | cardinality: -1 18 | translatable: true 19 | indexes: { } 20 | persist_with_no_fields: false 21 | custom_storage: false 22 | -------------------------------------------------------------------------------- /config/install/field.storage.node.field_element_symbol.yml: -------------------------------------------------------------------------------- 1 | uuid: c625c33c-5baf-43da-968c-b936c9eacc6c 2 | langcode: en 3 | status: true 4 | dependencies: 5 | module: 6 | - node 7 | id: node.field_element_symbol 8 | field_name: field_element_symbol 9 | entity_type: node 10 | type: string 11 | settings: 12 | max_length: 4 13 | is_ascii: false 14 | case_sensitive: false 15 | module: core 16 | locked: false 17 | cardinality: 1 18 | translatable: true 19 | indexes: { } 20 | persist_with_no_fields: false 21 | custom_storage: false 22 | -------------------------------------------------------------------------------- /config/install/field.storage.node.field_one_liner.yml: -------------------------------------------------------------------------------- 1 | uuid: f1010262-d738-4052-a033-c2d1c0f60a48 2 | langcode: en 3 | status: true 4 | dependencies: 5 | module: 6 | - node 7 | id: node.field_one_liner 8 | field_name: field_one_liner 9 | entity_type: node 10 | type: string 11 | settings: 12 | max_length: 255 13 | is_ascii: false 14 | case_sensitive: false 15 | module: core 16 | locked: false 17 | cardinality: 1 18 | translatable: true 19 | indexes: { } 20 | persist_with_no_fields: false 21 | custom_storage: false 22 | -------------------------------------------------------------------------------- /config/install/language.content_settings.node.article.yml: -------------------------------------------------------------------------------- 1 | uuid: b26dbe86-56ba-41a2-99a5-1043fa4e5539 2 | langcode: en 3 | status: true 4 | dependencies: 5 | config: 6 | - node.type.article 7 | module: 8 | - content_translation 9 | third_party_settings: 10 | content_translation: 11 | enabled: true 12 | id: node.article 13 | target_entity_type_id: node 14 | target_bundle: article 15 | default_langcode: und 16 | language_alterable: true 17 | -------------------------------------------------------------------------------- /config/install/language.content_settings.node.element.yml: -------------------------------------------------------------------------------- 1 | uuid: 36a823dc-e703-4750-b1d5-cefe846e2f1e 2 | langcode: en 3 | status: true 4 | dependencies: 5 | config: 6 | - node.type.element 7 | module: 8 | - content_translation 9 | third_party_settings: 10 | content_translation: 11 | enabled: true 12 | id: node.element 13 | target_entity_type_id: node 14 | target_bundle: element 15 | default_langcode: site_default 16 | language_alterable: false 17 | -------------------------------------------------------------------------------- /config/install/language.entity.es.yml: -------------------------------------------------------------------------------- 1 | uuid: d0532dc7-59e0-4989-ba5d-841387dd474a 2 | langcode: en 3 | status: true 4 | dependencies: { } 5 | id: es 6 | label: Spanish 7 | direction: ltr 8 | weight: 1 9 | locked: false 10 | -------------------------------------------------------------------------------- /config/install/language.entity.fr.yml: -------------------------------------------------------------------------------- 1 | uuid: 49b47acc-6e45-4900-8691-892d97ee33a8 2 | langcode: en 3 | status: true 4 | dependencies: { } 5 | id: fr 6 | label: French 7 | direction: ltr 8 | weight: 2 9 | locked: false 10 | -------------------------------------------------------------------------------- /config/install/migrate_plus.migration.example_creature_base.yml: -------------------------------------------------------------------------------- 1 | # Migration of "article" node data from Drupal 7. 2 | # 3 | # This file demonstrates migration of content translated with 4 | # the 'entity_translation' module. 5 | # 6 | # Since a detailed description of many configuration parameters 7 | # has been provided in the 'hybrid_base' and 'hybrid_i18n' migrations, 8 | # they have not been repeated here. Kindly refer to those migrations 9 | # if you are looking for detailed descriptions for various paramters. 10 | 11 | # Migration metadata 12 | id: example_creature_base 13 | label: Creature base data 14 | migration_group: example_creature 15 | migration_tags: 16 | - node 17 | - article 18 | - d7 19 | # Migration source 20 | source: 21 | # Ignoring translations! The tricky part! 22 | # 23 | # The Drupal 7 version of the migration source Node does not 24 | # support the "translations" parameter at this moment. Hence, 25 | # even if you specify "translations: flase" (or omit that line), 26 | # all nodes, including translations, are imported. 27 | # 28 | # To prevent this, I chose to write the method D7NodeEntityTranslation::query(). 29 | plugin: d7_node_entity_translation 30 | # The type of nodes we want to migrate. 31 | node_type: article 32 | # Specify source database. 33 | key: drupal_7_entity 34 | # Static values for the migration. 35 | constants: 36 | uid_root: 1 37 | node_article: 'article' 38 | # Migration destination 39 | destination: 40 | plugin: 'entity:node' 41 | # Migration processes 42 | process: 43 | type: constants/node_article 44 | langcode: 45 | plugin: default_value 46 | source: language 47 | default_value: und 48 | title: title 49 | body: body 50 | field_one_liner: field_one_liner 51 | uid: 'constants/uid_root' 52 | sticky: sticky 53 | status: status 54 | promote: promote 55 | # General dependencies 56 | dependencies: 57 | enforced: 58 | module: 59 | - migrate_example_i18n 60 | -------------------------------------------------------------------------------- /config/install/migrate_plus.migration.example_creature_i18n.yml: -------------------------------------------------------------------------------- 1 | # Migration of "article" node translations from Drupal 7. 2 | # 3 | # This file demonstrates migration of content translated with 4 | # the 'entity_translation' module. 5 | # 6 | # Since a detailed description of many configuration parameters 7 | # has been provided in the 'hybrid_base' and 'hybrid_i18n' migrations, 8 | # they have not been repeated here. Kindly refer to those migrations 9 | # if you are looking for detailed descriptions for various paramters. 10 | 11 | # Migration metadata 12 | id: example_creature_i18n 13 | label: Creature translations 14 | migration_group: example_creature 15 | migration_tags: 16 | - node 17 | - article 18 | - d7 19 | # Migration source 20 | source: 21 | plugin: d7_node_entity_translation 22 | node_type: article 23 | # We deal only with translations in this migration. 24 | translations: true 25 | # Specify the database from which data is to be read. 26 | key: drupal_7_entity 27 | # Static values for the migration. 28 | constants: 29 | uid_root: 1 30 | node_article: 'article' 31 | ids: 32 | - nid 33 | - language 34 | # Migration destination 35 | destination: 36 | plugin: 'entity:node' 37 | # Important! Create translations for existing nodes. 38 | translations: true 39 | # Migration processes 40 | process: 41 | type: constants/node_article 42 | # Attach the translation to the already migrated base node. 43 | nid: 44 | plugin: migration 45 | migration: example_creature_base 46 | source: nid 47 | langcode: language 48 | # Another catch! Since we have used the 'title' module to 49 | # translate node titles, we need to assign the special field 50 | # 'title_field' to the 'title' of our destination nodes to 51 | # ensure that we get the translated titles. 52 | title: title_field 53 | body: body 54 | field_one_liner: field_one_liner 55 | uid: 'constants/uid_root' 56 | sticky: sticky 57 | status: status 58 | promote: promote 59 | # Migration dependencies 60 | migration_dependencies: 61 | required: 62 | - example_creature_base 63 | # General dependencies 64 | dependencies: 65 | enforced: 66 | module: 67 | - migrate_example_i18n 68 | -------------------------------------------------------------------------------- /config/install/migrate_plus.migration.example_dog_base.yml: -------------------------------------------------------------------------------- 1 | # Migration of "article" node data from Drupal 7. 2 | # 3 | # This file demonstrates migration of content translated with 4 | # the 'content_translation' module. 5 | # 6 | # Since a detailed description of many configuration parameters 7 | # has been provided in the 'hybrid_base' and 'hybrid_i18n' migrations, 8 | # they have not been repeated here. Kindly refer to those migrations 9 | # if you are looking for detailed descriptions for various paramters. 10 | 11 | # Migration metadata 12 | id: example_dog_base 13 | label: Dog base data 14 | migration_group: example_dog 15 | migration_tags: 16 | - node 17 | - article 18 | - d7 19 | # Migration source 20 | source: 21 | # Since Drupal 8.3.x, Drupal 7 content translations are supported out of the 22 | # box. However, if you are using an older version of Drupal 8, you can check 23 | # out the D7NodeContentTranslation source plugin included in this module. 24 | plugin: d7_node 25 | # The type of nodes we want to migrate. 26 | node_type: article 27 | # Specify source database. 28 | key: drupal_7_content 29 | # Static values for the migration. 30 | constants: 31 | uid_root: 1 32 | node_article: 'article' 33 | # Migration destination 34 | destination: 35 | plugin: 'entity:node' 36 | # Migration processes 37 | process: 38 | # Specify the type of node we wish to create. 39 | type: constants/node_article 40 | # Destination node language. 41 | langcode: 42 | plugin: default_value 43 | source: language 44 | default_value: und 45 | # We assign the root user as the author of migrated nodes. 46 | uid: 'constants/uid_root' 47 | # Some other properties which we migrate as is. 48 | title: title 49 | body: body 50 | field_one_liner: field_one_liner 51 | sticky: sticky 52 | status: status 53 | promote: promote 54 | # General dependencies 55 | dependencies: 56 | enforced: 57 | module: 58 | - migrate_example_i18n 59 | -------------------------------------------------------------------------------- /config/install/migrate_plus.migration.example_dog_i18n.yml: -------------------------------------------------------------------------------- 1 | # Migration of "article" node translations from Drupal 7. 2 | # 3 | # Since a detailed description of many configuration parameters 4 | # has been provided in the 'hybrid_base' and 'hybrid_i18n' migrations, 5 | # they have not been repeated here. Kindly refer to those migrations 6 | # if you are looking for detailed descriptions for various paramters. 7 | 8 | # Migration metadata 9 | id: example_dog_i18n 10 | label: Dog translations 11 | migration_group: example_dog 12 | migration_tags: 13 | - node 14 | - article 15 | - d7 16 | # Migration source 17 | source: 18 | plugin: d7_node 19 | node_type: article 20 | # We deal only with translations in this migration. 21 | translations: true 22 | # Specify source database. 23 | key: drupal_7_content 24 | # Static values for the migration. 25 | constants: 26 | uid_root: 1 27 | node_article: 'article' 28 | # Migration destination 29 | destination: 30 | plugin: 'entity:node' 31 | default_bundle: article 32 | translations: true 33 | # Migration processes 34 | process: 35 | # Attach the translation to the already migrated base node. 36 | nid: 37 | plugin: migration 38 | migration: example_dog_base 39 | source: tnid 40 | type: constants/node_article 41 | title: title 42 | body: body 43 | field_one_liner: field_one_liner 44 | langcode: language 45 | uid: 'constants/uid_root' 46 | sticky: sticky 47 | status: status 48 | promote: promote 49 | # Migration dependencies 50 | migration_dependencies: 51 | required: 52 | - example_dog_base 53 | # General dependencies 54 | dependencies: 55 | enforced: 56 | module: 57 | - migrate_example_i18n 58 | -------------------------------------------------------------------------------- /config/install/migrate_plus.migration.example_element_en.yml: -------------------------------------------------------------------------------- 1 | # Migration of data from CSV into content type "element". 2 | # 3 | # Many configuration parameters are described in the 'example_hybrid_base' and 4 | # 'example_hybrid_i18n' migrations, refer to those for more information. 5 | # 6 | # General metadata 7 | id: example_element_en 8 | label: Element data in English 9 | migration_group: example_element 10 | migration_tags: 11 | - node 12 | - element 13 | - csv 14 | # Migration source 15 | source: 16 | # We will be importing from a CSV file, so we need the 17 | # 'migrate_source_csv' module. It provides a source with the ID 'csv. 18 | plugin: csv 19 | # Specify the name of the CSV file, which lives in the directory 20 | # import/element. See migrate_example_i18n_migration_plugins_alter() for how 21 | # this is found. 22 | path: 'element.data.en.csv' 23 | # Number of rows at the beginning which are not actual data. 24 | header_row_count: 1 25 | # The unique ID for each row is in this column. 26 | keys: 27 | - Symbol 28 | # Legend of source fields. 29 | # 30 | # The keys are the column names as they appear in the CSV 31 | # and the values are descriptions which would appear in the UI. 32 | fields: 33 | Name: 'Name' 34 | Symbol: 'Symbol' 35 | 'Atomic Number': 'Atomic number' 36 | 'Discovered By': 'Name of people who discovered the element' 37 | # Constant values for the migration. 38 | constants: 39 | lang_en: en 40 | node_element: 'element' 41 | # Migration destination 42 | destination: 43 | plugin: 'entity:node' 44 | # Migration processes 45 | process: 46 | # We simply map most of the source fields to the destination. 47 | type: constants/node_element 48 | title: Name 49 | langcode: constants/lang_en 50 | field_element_symbol: Symbol 51 | # The 'Discovered By' column contains comma-separated values. 52 | # We use the 'explode' plugin to split it into an array of values. 53 | field_element_discoverer: 54 | plugin: explode 55 | delimiter: ', ' 56 | source: Discovered By 57 | # General dependencies 58 | dependencies: 59 | enforced: 60 | module: 61 | - migrate_example_i18n 62 | -------------------------------------------------------------------------------- /config/install/migrate_plus.migration.example_element_es.yml: -------------------------------------------------------------------------------- 1 | # Migration of data from CSV into translations of content type "element". 2 | # 3 | # Many configuration parameters are described in the 'example_hybrid_base' and 4 | # 'example_hybrid_i18n' migrations, refer to those for more information. 5 | # 6 | # The untranslated data for "element" nodes comes from 'example_element_en', so 7 | # refer to that before reading this. 8 | # 9 | # General metadata 10 | id: example_element_es 11 | label: Element data in Spanish 12 | migration_group: example_element 13 | migration_tags: 14 | - node 15 | - element 16 | - csv 17 | # Migration source 18 | source: 19 | # We will be importing from a CSV file, so we need the 20 | # 'migrate_source_csv' module. It provides a source with the ID 'csv. 21 | plugin: csv 22 | # Specify the name of the CSV file, which lives in the directory 23 | # import/element. See migrate_example_i18n_migration_plugins_alter() for how 24 | # this is found. 25 | path: 'element.data.es.csv' 26 | # Number of rows at the beginning which are not actual data. 27 | header_row_count: 1 28 | # The unique ID for each row is in this column. 29 | # 30 | # Special characters are not supported in column names, so I renamed 31 | # fields to remove accents. Eg: 'Símbolo' becomes 'Simbolo', 32 | # (without an accent on the 'i'). 33 | keys: 34 | - 'Simbolo' 35 | # Legend of source fields. 36 | fields: 37 | 'Simbolo': 'Symbol' 38 | Nombre: 'Name' 39 | 'Numero atomico': 'Atomic number' 40 | 'Masa atomica': 'Atomic mass' 41 | # Static values for the migration. 42 | constants: 43 | lang_es: es 44 | node_element: 'element' 45 | # Migration destination 46 | destination: 47 | plugin: 'entity:node' 48 | # Important! Create translations for existing nodes. 49 | translations: true 50 | # Migration processes 51 | process: 52 | # Attach the translation to the already-migrated node. 53 | nid: 54 | plugin: migration 55 | source: Simbolo 56 | migration: example_element_en 57 | # For the rest of the fields, migrate them as is. 58 | type: constants/node_element 59 | title: Nombre 60 | langcode: constants/lang_es 61 | # Migration dependencies 62 | migration_dependencies: 63 | required: 64 | - example_element_en 65 | # General dependencies 66 | dependencies: 67 | enforced: 68 | module: 69 | - migrate_example_i18n 70 | - content_translation 71 | -------------------------------------------------------------------------------- /config/install/migrate_plus.migration.example_hybrid_base.yml: -------------------------------------------------------------------------------- 1 | # Migrate of nodes of type "story" from Drupal 6 to Drupal 8. 2 | # 3 | # This file demonstrates migration of content translated with 4 | # the D6 'content_translation' module. 5 | # 6 | # Many configuration parameters are described in detail in this 7 | # file, so it's a good starting point. 8 | 9 | # Migration metadata 10 | id: example_hybrid_base 11 | label: Hybrid base data 12 | # Migrations can be organized into groups, one group per migration. 13 | migration_group: example_hybrid 14 | # Migrations can also be organized by tags, potentially many tags per 15 | # migration. 16 | migration_tags: 17 | - node 18 | - story 19 | - d6 20 | # Migration source 21 | source: 22 | # Since we want to migrate nodes from Drupal 6, we need to 23 | # use the 'd6_node' source plugin. The plugin icomes with core's 24 | # 'migrate_drupal' module. 25 | # 26 | # If you need additional functionality, you can create a custom 27 | # plugin that extends this one. See the example_dog_base migration 28 | # for an example of that. 29 | plugin: d6_node 30 | # The type of nodes we want to migrate. 31 | # 32 | # This parameter tells the source plugin that only nodes of 33 | # type 'story' are to be read from the Drupal 6 database. 34 | node_type: story 35 | # Specify source database. 36 | # 37 | # The database settings need to be defined in the global 38 | # $databases variable. See the sample 'settings.local.php' 39 | # file provided in the project to learn how to add these 40 | # settings. For this example, the settings are in 41 | # $databases['drupal_6']. 42 | key: drupal_6 43 | # Constant values for the migration. 44 | constants: 45 | node_article: article 46 | body_format: full_html 47 | # Migration destination 48 | destination: 49 | # Since we want to create 'node' entities from the source data, 50 | # we specify 'entity:node' as the destination plugin. 51 | plugin: 'entity:node' 52 | # Migration processes 53 | # This does the mapping between source fields and destination fields. 54 | process: 55 | # The type of node we wish to create, in this case 'article'. 56 | type: constants/node_article 57 | # Destination node language. 58 | # If the D6 node is "Language neutral", this will be empty. So 59 | # default it to 'und'. 60 | langcode: 61 | plugin: default_value 62 | source: language 63 | default_value: und 64 | # The body is a special case, since it has both a value and a format. 65 | # We assign body data as the value, and 'full_html' as the format. 66 | 'body/value': body 67 | 'body/format': constants/body_format 68 | # Some other properties which we migrate as-is. 69 | title: title 70 | field_one_liner: field_one_liner 71 | sticky: sticky 72 | status: status 73 | promote: promote 74 | # General dependencies 75 | # 76 | # This migration depends on our custom module. If the module is 77 | # uninstalled, the configuration should also be uninstalled. 78 | dependencies: 79 | enforced: 80 | module: 81 | - migrate_example_i18n 82 | -------------------------------------------------------------------------------- /config/install/migrate_plus.migration.example_hybrid_i18n.yml: -------------------------------------------------------------------------------- 1 | # Migrate of nodes of type "story" from Drupal 6 to Drupal 8. 2 | # 3 | # This file demonstrates migration of content translated with 4 | # the D6 'content_translation' module. 5 | # 6 | # The untranslated data for "story" nodes comes from 'example_hybrid_base', 7 | # so refer to that before reading this. 8 | 9 | # Migration metadata 10 | id: example_hybrid_i18n 11 | label: Hybrid translations 12 | migration_group: example_hybrid 13 | migration_tags: 14 | - node 15 | - story 16 | - d6 17 | # Migration source 18 | source: 19 | plugin: d6_node 20 | node_type: story 21 | # We want this source to give us only translations of nodes, not the 22 | # original languages. 23 | translations: true 24 | # Specify source database. 25 | key: drupal_6 26 | # Constant values for the migration. 27 | constants: 28 | body_format: full_html 29 | node_article: article 30 | # Migration destination 31 | destination: 32 | plugin: 'entity:node' 33 | # Important! Create translations for existing nodes. 34 | # 35 | # This tells the destination plugin not to create a new node for 36 | # each record. Instead, it should add translations to existing 37 | # nodes. 38 | translations: true 39 | # Migration processes 40 | # This does the mapping between source fields and destination fields. 41 | process: 42 | type: constants/node_article 43 | # The example_hybrid_base migrations has already created 44 | # untranslated nodes. We want to add our translation 45 | # to that existing node. How do we do that? 46 | # 47 | # The earlier example_hybrid_base migration identified each source 48 | # D6 node with its 'tnid' property. For each such node, it created 49 | # a D8 node, which has a 'nid'. Every time it did that, it recorded 50 | # a mapping between those values, eg: 51 | # 52 | # +-------------+-----------------+ 53 | # | source_tnid | destination_nid | 54 | # +-------------+-----------------+ 55 | # | 5 | 8 | 56 | # | 6 | 9 | 57 | # | 8 | 10 | 58 | # | ... | ... | 59 | # +-------------+-----------------+ 60 | # 61 | # In the current example_hybrid_i18n migration, we use the 'migration' 62 | # plugin. This means: when you see a D6 source node, find its tnid, 63 | # and look it up in the table above. Use the resulting nid for the 64 | # destination node. 65 | # 66 | # For example, if a D6 node has tnid = 6, the migration will look it 67 | # up in the table, and find that the destination nid is 9. Then it 68 | # knows to add the translation to the node with that nid. 69 | nid: 70 | plugin: migration 71 | source: tnid 72 | migration: example_hybrid_base 73 | langcode: language 74 | title: title 75 | 'body/format': constants/body_format 76 | 'body/value': body 77 | field_one_liner: field_one_liner 78 | sticky: sticky 79 | status: status 80 | promote: promote 81 | # Migration dependencies 82 | # 83 | # This migration needs untranslated nodes to already exist, so 84 | # mark it as dependent on the example_hybrid_base migration. 85 | migration_dependencies: 86 | required: 87 | - example_hybrid_base 88 | # General dependencies 89 | dependencies: 90 | enforced: 91 | module: 92 | - migrate_example_i18n 93 | -------------------------------------------------------------------------------- /config/install/migrate_plus.migration_group.example_creature.yml: -------------------------------------------------------------------------------- 1 | # Migration group 'creature' migrations 2 | id: example_creature 3 | label: Creature migration 4 | description: Migration of mythological creature data from Drupal 7 (entity translations). 5 | source_type: Drupal 7 database 6 | dependencies: 7 | enforced: 8 | module: 9 | - migrate_example_i18n 10 | -------------------------------------------------------------------------------- /config/install/migrate_plus.migration_group.example_dog.yml: -------------------------------------------------------------------------------- 1 | # Migration group 'dog' migrations 2 | id: example_dog 3 | label: Dog migration 4 | description: Migration of dog data from Drupal 7 (content translations). 5 | source_type: Drupal 7 database 6 | dependencies: 7 | enforced: 8 | module: 9 | - migrate_example_i18n 10 | -------------------------------------------------------------------------------- /config/install/migrate_plus.migration_group.example_element.yml: -------------------------------------------------------------------------------- 1 | # Migration group 'element' migrations 2 | id: example_element 3 | label: Element migration 4 | description: Migration of chemical element data (non-Drupal source). 5 | source_type: CSV files 6 | dependencies: 7 | enforced: 8 | module: 9 | - migrate_example_i18n 10 | -------------------------------------------------------------------------------- /config/install/migrate_plus.migration_group.example_hybrid.yml: -------------------------------------------------------------------------------- 1 | # Migration group 'hybrid' migrations 2 | id: example_hybrid 3 | label: Hybrid migration 4 | description: Migration of animal hybrid data from Drupal 6 (content translations). 5 | source_type: Drupal 6 database 6 | dependencies: 7 | enforced: 8 | module: 9 | - migrate_example_i18n 10 | -------------------------------------------------------------------------------- /config/install/node.type.element.yml: -------------------------------------------------------------------------------- 1 | uuid: b4587545-bcc0-4f50-abc4-8ec93ddf200c 2 | langcode: en 3 | status: true 4 | dependencies: 5 | module: 6 | - menu_ui 7 | third_party_settings: 8 | menu_ui: 9 | available_menus: { } 10 | parent: '' 11 | name: Element 12 | type: element 13 | description: 'Use Element to add chemical elements to your website.' 14 | help: '' 15 | new_revision: false 16 | preview_mode: 1 17 | display_submitted: false 18 | -------------------------------------------------------------------------------- /config/install/views.view.elements.yml: -------------------------------------------------------------------------------- 1 | uuid: f7c963f2-c98e-448a-be19-648e6614ac5a 2 | langcode: en 3 | status: true 4 | dependencies: 5 | config: 6 | - core.entity_view_mode.node.teaser 7 | - field.storage.node.field_element_discoverer 8 | - field.storage.node.field_element_symbol 9 | - node.type.element 10 | - system.menu.main 11 | module: 12 | - node 13 | - user 14 | id: elements 15 | label: Elements 16 | module: views 17 | description: '' 18 | tag: '' 19 | base_table: node_field_data 20 | base_field: nid 21 | core: 8.x 22 | display: 23 | default: 24 | display_plugin: default 25 | id: default 26 | display_title: Master 27 | position: 0 28 | display_options: 29 | access: 30 | type: perm 31 | options: 32 | perm: 'access content' 33 | cache: 34 | type: tag 35 | options: { } 36 | query: 37 | type: views_query 38 | options: 39 | disable_sql_rewrite: false 40 | distinct: false 41 | replica: false 42 | query_comment: '' 43 | query_tags: { } 44 | exposed_form: 45 | type: basic 46 | options: 47 | submit_button: Apply 48 | reset_button: false 49 | reset_button_label: Reset 50 | exposed_sorts_label: 'Sort by' 51 | expose_sort_order: true 52 | sort_asc_label: Asc 53 | sort_desc_label: Desc 54 | pager: 55 | type: mini 56 | options: 57 | items_per_page: 25 58 | offset: 0 59 | id: 0 60 | total_pages: null 61 | tags: 62 | previous: ‹‹ 63 | next: ›› 64 | expose: 65 | items_per_page: false 66 | items_per_page_label: 'Items per page' 67 | items_per_page_options: '5, 10, 25, 50' 68 | items_per_page_options_all: false 69 | items_per_page_options_all_label: '- All -' 70 | offset: false 71 | offset_label: Offset 72 | style: 73 | type: table 74 | options: 75 | grouping: { } 76 | row_class: '' 77 | default_row_class: true 78 | override: true 79 | sticky: false 80 | caption: '' 81 | summary: '' 82 | description: '' 83 | columns: 84 | title: title 85 | info: 86 | title: 87 | sortable: false 88 | default_sort_order: asc 89 | align: '' 90 | separator: '' 91 | empty_column: false 92 | responsive: '' 93 | default: title 94 | empty_table: false 95 | row: 96 | type: 'entity:node' 97 | options: 98 | view_mode: teaser 99 | fields: 100 | field_element_symbol: 101 | id: field_element_symbol 102 | table: node__field_element_symbol 103 | field: field_element_symbol 104 | relationship: none 105 | group_type: group 106 | admin_label: '' 107 | label: Symbol 108 | exclude: false 109 | alter: 110 | alter_text: false 111 | text: '' 112 | make_link: false 113 | path: '' 114 | absolute: false 115 | external: false 116 | replace_spaces: false 117 | path_case: none 118 | trim_whitespace: false 119 | alt: '' 120 | rel: '' 121 | link_class: '' 122 | prefix: '' 123 | suffix: '' 124 | target: '' 125 | nl2br: false 126 | max_length: 0 127 | word_boundary: true 128 | ellipsis: true 129 | more_link: false 130 | more_link_text: '' 131 | more_link_path: '' 132 | strip_tags: false 133 | trim: false 134 | preserve_tags: '' 135 | html: false 136 | element_type: '' 137 | element_class: '' 138 | element_label_type: '' 139 | element_label_class: '' 140 | element_label_colon: true 141 | element_wrapper_type: '' 142 | element_wrapper_class: '' 143 | element_default_classes: true 144 | empty: '' 145 | hide_empty: false 146 | empty_zero: false 147 | hide_alter_empty: true 148 | click_sort_column: value 149 | type: string 150 | settings: 151 | link_to_entity: false 152 | group_column: value 153 | group_columns: { } 154 | group_rows: true 155 | delta_limit: 0 156 | delta_offset: 0 157 | delta_reversed: false 158 | delta_first_last: false 159 | multi_type: separator 160 | separator: ', ' 161 | field_api_classes: false 162 | plugin_id: field 163 | title: 164 | id: title 165 | table: node_field_data 166 | field: title 167 | relationship: none 168 | group_type: group 169 | admin_label: '' 170 | label: Name 171 | exclude: false 172 | alter: 173 | alter_text: false 174 | text: '' 175 | make_link: false 176 | path: '' 177 | absolute: false 178 | external: false 179 | replace_spaces: false 180 | path_case: none 181 | trim_whitespace: false 182 | alt: '' 183 | rel: '' 184 | link_class: '' 185 | prefix: '' 186 | suffix: '' 187 | target: '' 188 | nl2br: false 189 | max_length: 0 190 | word_boundary: false 191 | ellipsis: false 192 | more_link: false 193 | more_link_text: '' 194 | more_link_path: '' 195 | strip_tags: false 196 | trim: false 197 | preserve_tags: '' 198 | html: false 199 | element_type: '' 200 | element_class: '' 201 | element_label_type: '' 202 | element_label_class: '' 203 | element_label_colon: true 204 | element_wrapper_type: '' 205 | element_wrapper_class: '' 206 | element_default_classes: true 207 | empty: '' 208 | hide_empty: false 209 | empty_zero: false 210 | hide_alter_empty: true 211 | click_sort_column: value 212 | type: string 213 | settings: 214 | link_to_entity: true 215 | group_column: value 216 | group_columns: { } 217 | group_rows: true 218 | delta_limit: 0 219 | delta_offset: 0 220 | delta_reversed: false 221 | delta_first_last: false 222 | multi_type: separator 223 | separator: ', ' 224 | field_api_classes: false 225 | entity_type: node 226 | entity_field: title 227 | plugin_id: field 228 | field_element_discoverer: 229 | id: field_element_discoverer 230 | table: node__field_element_discoverer 231 | field: field_element_discoverer 232 | relationship: none 233 | group_type: group 234 | admin_label: '' 235 | label: Discoverers 236 | exclude: false 237 | alter: 238 | alter_text: false 239 | text: '' 240 | make_link: false 241 | path: '' 242 | absolute: false 243 | external: false 244 | replace_spaces: false 245 | path_case: none 246 | trim_whitespace: false 247 | alt: '' 248 | rel: '' 249 | link_class: '' 250 | prefix: '' 251 | suffix: '' 252 | target: '' 253 | nl2br: false 254 | max_length: 0 255 | word_boundary: true 256 | ellipsis: true 257 | more_link: false 258 | more_link_text: '' 259 | more_link_path: '' 260 | strip_tags: false 261 | trim: false 262 | preserve_tags: '' 263 | html: false 264 | element_type: '' 265 | element_class: '' 266 | element_label_type: '' 267 | element_label_class: '' 268 | element_label_colon: true 269 | element_wrapper_type: '' 270 | element_wrapper_class: '' 271 | element_default_classes: true 272 | empty: '' 273 | hide_empty: false 274 | empty_zero: false 275 | hide_alter_empty: true 276 | click_sort_column: value 277 | type: string 278 | settings: 279 | link_to_entity: false 280 | group_column: value 281 | group_columns: { } 282 | group_rows: true 283 | delta_limit: 0 284 | delta_offset: 0 285 | delta_reversed: false 286 | delta_first_last: false 287 | multi_type: separator 288 | separator: ', ' 289 | field_api_classes: false 290 | plugin_id: field 291 | filters: 292 | status: 293 | value: '1' 294 | table: node_field_data 295 | field: status 296 | plugin_id: boolean 297 | entity_type: node 298 | entity_field: status 299 | id: status 300 | expose: 301 | operator: '' 302 | group: 1 303 | type: 304 | id: type 305 | table: node_field_data 306 | field: type 307 | value: 308 | element: element 309 | entity_type: node 310 | entity_field: type 311 | plugin_id: bundle 312 | langcode: 313 | id: langcode 314 | table: node_field_data 315 | field: langcode 316 | relationship: none 317 | group_type: group 318 | admin_label: '' 319 | operator: in 320 | value: 321 | '***LANGUAGE_language_interface***': '***LANGUAGE_language_interface***' 322 | group: 1 323 | exposed: false 324 | expose: 325 | operator_id: '' 326 | label: '' 327 | description: '' 328 | use_operator: false 329 | operator: '' 330 | identifier: '' 331 | required: false 332 | remember: false 333 | multiple: false 334 | remember_roles: 335 | authenticated: authenticated 336 | reduce: false 337 | is_grouped: false 338 | group_info: 339 | label: '' 340 | description: '' 341 | identifier: '' 342 | optional: true 343 | widget: select 344 | multiple: false 345 | remember: false 346 | default_group: All 347 | default_group_multiple: { } 348 | group_items: { } 349 | entity_type: node 350 | entity_field: langcode 351 | plugin_id: language 352 | sorts: 353 | title: 354 | id: title 355 | table: node_field_data 356 | field: title 357 | order: ASC 358 | entity_type: node 359 | entity_field: title 360 | plugin_id: standard 361 | relationship: none 362 | group_type: group 363 | admin_label: '' 364 | exposed: false 365 | expose: 366 | label: '' 367 | title: Elements 368 | header: { } 369 | footer: { } 370 | empty: 371 | area: 372 | id: area 373 | table: views 374 | field: area 375 | relationship: none 376 | group_type: group 377 | admin_label: '' 378 | empty: true 379 | tokenize: false 380 | content: 381 | value: 'There are no items to display here!' 382 | format: basic_html 383 | plugin_id: text 384 | relationships: { } 385 | arguments: { } 386 | display_extenders: { } 387 | use_ajax: true 388 | cache_metadata: 389 | max-age: 0 390 | contexts: 391 | - 'languages:language_content' 392 | - 'languages:language_interface' 393 | - url.query_args 394 | - 'user.node_grants:view' 395 | - user.permissions 396 | tags: 397 | - 'config:field.storage.node.field_element_discoverer' 398 | - 'config:field.storage.node.field_element_symbol' 399 | page: 400 | display_plugin: page 401 | id: page 402 | display_title: Page 403 | position: 1 404 | display_options: 405 | display_extenders: { } 406 | path: elements 407 | rendering_language: '***LANGUAGE_entity_translation***' 408 | menu: 409 | type: normal 410 | title: Elements 411 | description: '' 412 | expanded: false 413 | parent: '' 414 | weight: -49 415 | context: '0' 416 | menu_name: main 417 | cache_metadata: 418 | max-age: 0 419 | contexts: 420 | - 'languages:language_content' 421 | - 'languages:language_interface' 422 | - url.query_args 423 | - 'user.node_grants:view' 424 | - user.permissions 425 | tags: 426 | - 'config:field.storage.node.field_element_discoverer' 427 | - 'config:field.storage.node.field_element_symbol' 428 | -------------------------------------------------------------------------------- /dump/Makefile: -------------------------------------------------------------------------------- 1 | # The site/instance to prepare. 2 | SITE=default 3 | 4 | # Prepare Drupal 6 installation with "content_translation" 5 | d6: 6 | drush use $(SITE) 7 | drush dl i18n cck toolbar views wysiwyg -y 8 | drush en content_translation cck toolbar views wysiwyg -y 9 | drush cc all 10 | exit; 11 | 12 | # Prepare Drupal 7 installation with "content_translation" 13 | d7_content_tran: 14 | drush use $(SITE) 15 | drush dl i18n views wysiwyg -y 16 | drush cc all 17 | exit; 18 | 19 | # Prepare Drupal 7 installation with "entity_translation" 20 | d7_entity_tran: 21 | drush use $(SITE) 22 | drush dl entity_translation title views wysiwyg -y 23 | drush cc all 24 | exit; 25 | 26 | # Prepare Drupal 8 installation for running this module. 27 | d8: 28 | drush use $(SITE) 29 | drush dl migrate_plus migrate_tools migrate_source_csv -y 30 | drush en migrate_example_i18n -y 31 | drush cr 32 | exit; 33 | -------------------------------------------------------------------------------- /dump/settings.local.php: -------------------------------------------------------------------------------- 1 | 'sandbox_d8', 23 | 'username' => 'root', 24 | 'password' => 'f00b@r', 25 | 'prefix' => '', 26 | 'host' => '127.0.0.1', 27 | 'port' => '3306', 28 | 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql', 29 | 'driver' => 'mysql', 30 | ); 31 | 32 | // Migration database: Drupal 6 33 | $databases['drupal_6']['default'] = array( 34 | 'database' => 'sandbox_d6', 35 | 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql', 36 | 'driver' => 'mysql', 37 | 'username' => 'root', 38 | 'password' => 'f00b@r', 39 | 'prefix' => '', 40 | 'host' => '127.0.0.1', 41 | 'port' => '3306', 42 | ); 43 | 44 | // Migration database: Drupal 7 45 | // Uses 'content_translation' and 'i18n' modules for i18n. 46 | $databases['drupal_7_content']['default'] = array( 47 | 'database' => 'sandbox_d7_content', 48 | 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql', 49 | 'driver' => 'mysql', 50 | 'username' => 'root', 51 | 'password' => 'f00b@r', 52 | 'prefix' => '', 53 | 'host' => '127.0.0.1', 54 | 'port' => '3306', 55 | ); 56 | 57 | // Migration database: Drupal 7 58 | // Uses 'entity_translation' and 'title' modules for i18n. 59 | $databases['drupal_7_entity']['default'] = array( 60 | 'database' => 'sandbox_d7_entity', 61 | 'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql', 62 | 'driver' => 'mysql', 63 | 'username' => 'root', 64 | 'password' => 'f00b@r', 65 | 'prefix' => '', 66 | 'host' => '127.0.0.1', 67 | 'port' => '3306', 68 | ); 69 | 70 | // Other parameters. 71 | $settings['install_profile'] = 'standard'; 72 | $config_directories['sync'] = 'sites/sandbox.com/files/config_42DEULKiHpKmh-k1rSl9xFOg-DlL7hEO1kjqWcTlpIA1fI4OnSmVP45zmPp-T_pnZUi67Mq5MQ/sync'; 73 | -------------------------------------------------------------------------------- /import/README.md: -------------------------------------------------------------------------------- 1 | # Import data 2 | 3 | The _example\_element_ migrations import the CSV files found in this directory. Since this module could be installed in many potential places, a special hook is required to allow the migrations to find these files. See `migrate_example_i18n_migration_plugins_alter()` in `migrate_example_i18n.module`. 4 | -------------------------------------------------------------------------------- /import/element/element.data.en.csv: -------------------------------------------------------------------------------- 1 | Name,Symbol,Atomic Number,Discovered By 2 | Hydrogen,H,1,Henry Cavendish 3 | Helium,He,2,"Sir William Ramsey, Nils Langet, P.T.Cleve" 4 | Lithium,Li,3,Johann Arfwedson 5 | Beryllium,Be,4,"Fredrich Wöhler, A.A.Bussy" 6 | Boron,B,5,"Sir H. Davy, J.L. Gay-Lussac, L.J. Thénard" 7 | Carbon,C,6,Known to the ancients 8 | Nitrogen,N,7,Daniel Rutherford 9 | Oxygen,O,8,"Joseph Priestly, Carl Wilhelm Scheele" 10 | Fluorine,F,9,Henri Moissan 11 | Neon,Ne,10,"Sir William Ramsey, M.W. Travers" 12 | Sodium,Na,11,Sir Humphrey Davy 13 | Magnesium,Mg,12,Sir Humphrey Davy 14 | Aluminum,Al,13,Hans Christian Oersted 15 | Silicon,Si,14,Jöns Berzelius 16 | Phosphorus,P,15,Hennig Brand 17 | Sulfur,S,16,Known to the ancients. 18 | Chlorine,Cl,17,Carl Wilhelm Scheele 19 | Argon,Ar,18,"Sir William Ramsey, Baron Rayleigh" 20 | Potassium,K,19,Sir Humphrey Davy 21 | Calcium,Ca,20,Sir Humphrey Davy 22 | Scandium,Sc,21,Lars Nilson 23 | Titanium,Ti,22,William Gregor 24 | Vanadium,V,23,Nils Sefström 25 | Chromium,Cr,24,Louis Vauquelin 26 | Manganese,Mn,25,Johann Gahn 27 | Iron,Fe,26,Known to the ancients. 28 | Cobalt,Co,27,George Brandt 29 | Nickel,Ni,28,Axel Cronstedt 30 | Copper,Cu,29,Known to the ancients. 31 | Zinc,Zn,30,Known to the ancients. 32 | Gallium,Ga,31,Paul Émile Lecoq de Boisbaudran 33 | Germanium,Ge,32,Clemens Winkler 34 | Arsenic,As,33,Known to the ancients. 35 | Selenium,Se,34,Jöns Berzelius 36 | Bromine,Br,35,Antoine J. Balard 37 | Krypton,Kr,36,"Sir William Ramsey, M.W. Travers" 38 | Rubidium,Rb,37,"R. Bunsen, G. Kirchoff" 39 | Strontium,Sr,38,A. Crawford 40 | Yttrium,Y,39,Johann Gadolin 41 | Zirconium,Zr,40,Martin Klaproth 42 | Niobium,Nb,41,Charles Hatchet 43 | Molybdenum,Mo,42,Carl Wilhelm Scheele 44 | Technetium,Tc,43,"Carlo Perrier, Émillo Segrè" 45 | Ruthenium,Ru,44,Karl Klaus 46 | Rhodium,Rh,45,William Wollaston 47 | Palladium,Pd,46,William Wollaston 48 | Silver,Ag,47,Known to the ancients. 49 | Cadmium,Cd,48,Fredrich Stromeyer 50 | Indium,In,49,"Ferdinand Reich, T. Richter" 51 | Tin,Sn,50,Known to the ancients. 52 | Antimony,Sb,51,Known to the ancients. 53 | Tellurium,Te,52,Franz Müller von Reichenstein 54 | Iodine,I,53,Bernard Courtois 55 | Xenon,Xe,54,Sir William Ramsay; M. W. Travers 56 | Cesium,Cs,55,"Gustov Kirchoff, Robert Bunsen" 57 | Barium,Ba,56,Sir Humphrey Davy 58 | Lanthanum,La,57,Carl Mosander 59 | Cerium,Ce,58,"W. von Hisinger, J. Berzelius, M. Klaproth" 60 | Praseodymium,Pr,59,C.F. Aver von Welsbach 61 | Neodymium,Nd,60,C.F. Aver von Welsbach 62 | Promethium,Pm,61,"J.A. Marinsky, L.E. Glendenin, C.D. Coryell" 63 | Samarium,Sm,62,Paul Émile Lecoq de Boisbaudran 64 | Europium,Eu,63,Eugène Demarçay 65 | Gadolinium,Gd,64,Jean de Marignac 66 | Terbium,Tb,65,Carl Mosander 67 | Dysprosium,Dy,66,Paul Émile Lecoq de Boisbaudran 68 | Holmium,Ho,67,J.L. Soret 69 | Erbium,Er,68,Carl Mosander 70 | Thulium,Tm,69,Per Theodor Cleve 71 | Ytterbium,Yb,70,Jean de Marignac 72 | Lutetium,Lu,71,Georges Urbain 73 | Hafnium,Hf,72,"Dirk Coster, Georg von Hevesy" 74 | Tantalum,Ta,73,Anders Ekeberg 75 | Tungsten,W,74,Fausto and Juan José de Elhuyar 76 | Rhenium,Re,75,"Walter Noddack, Ida Tacke, Otto Berg" 77 | Osmium,Os,76,Smithson Tenant 78 | Iridium,Ir,77,"S.Tenant, A.F.Fourcory, L.N.Vauquelin, H.V.Collet-Descoltils" 79 | Platinum,Pt,78,Julius Scaliger 80 | Gold,Au,79,Known to the ancients. 81 | Mercury,Hg,80,Known to the ancients. 82 | Thallium,Tl,81,Sir William Crookes 83 | Lead,Pb,82,Known to the ancients. 84 | Bismuth,Bi,83,Known to the ancients. 85 | Polonium,Po,84,Pierre and Marie Curie 86 | Astatine,At,85,"D.R.Corson, K.R.MacKenzie, E.Segré" 87 | Radon,Rn,86,Fredrich Ernst Dorn 88 | Francium,Fr,87,Marguerite Derey 89 | Radium,Ra,88,Pierre and Marie Curie 90 | Actinium,Ac,89,André Debierne 91 | Thorium,Th,90,Jöns Berzelius 92 | Protactinium,Pa,91,"Fredrich Soddy, John Cranston, Otto Hahn, Lise Meitner" 93 | Uranium,U,92,Martin Klaproth 94 | Neptunium,Np,93,"E.M. McMillan, P.H. Abelson" 95 | Plutonium,Pu,94,"G.T.Seaborg, J.W.Kennedy, E.M.McMillan, A.C.Wohl" 96 | Americium,Am,95,"G.T.Seaborg, R.A.James, L.O.Morgan, A.Ghiorso" 97 | Curium,Cm,96,"G.T.Seaborg, R.A.James, A.Ghiorso" 98 | Berkelium,Bk,97,"G.T.Seaborg, S.G.Tompson, A.Ghiorso" 99 | Californium,Cf,98,"G.T.Seaborg, S.G.Tompson, A.Ghiorso, K.Street Jr." 100 | Einsteinium,Es,99,"Argonne, Los Alamos, U of Calif" 101 | Fermium,Fm,100,"Argonne, Los Alamos, U of Calif" 102 | Mendelevium,Md,101,"G.T.Seaborg, S.G.Tompson, A.Ghiorso, K.Street Jr." 103 | Nobelium,No,102,Nobel Institute for Physics 104 | Lawrencium,Lr,103,"A.Ghiorso, T.Sikkeland, A.E.Larsh, R.M.Latimer" 105 | Rutherfordium,Rf,104,"A. Ghiorso, et al" 106 | Hahnium,Ha,105,"A. Ghiorso, et al" 107 | Seaborgium,Sg,106,Soviet Nuclear Research/ U. of Cal at Berkeley 108 | Nielsbohrium,Ns,107,Heavy Ion Research Laboratory (HIRL) 109 | Hessium,Hs,108,Heavy Ion Research Laboratory (HIRL) 110 | Mietnerium,Mt,109,Heavy Ion Research Laboratory (HIRL) 111 | Unnunnilium,Unn,110,Heavy Ion Research Laboratory (HIRL) 112 | Unnununium,Unu,111,Heavy Ion Research Laboratory (HIRL) 113 | -------------------------------------------------------------------------------- /import/element/element.data.es.csv: -------------------------------------------------------------------------------- 1 | Simbolo,Nombre,Numero atomico,Masa atomica 2 | H,Hidrogeno,1,1.00794 3 | Li,Litio,3,6.941 4 | Na,Sodio,11,22.989768 5 | K,Potasio,19,39.0983 6 | Rb,Rubidio,37,85.4678 7 | Cs,Cesio,55,132.90543 8 | Fr,Francio,87,223.0197 9 | Be,Berilio,4,9.012182 10 | Mg,Magnesio,12,24.305 11 | Ca,Calcio,20,40.078 12 | Sr,Estroncio,38,87.62 13 | Ba,Bario,56,137.327 14 | Ra,Radio,88,226.0254 15 | Sc,Escandio,21,44.956 16 | Y,Itrio,39,88.905 17 | La,Lantano,57,138.91 18 | Ac,Actinio,89,227 19 | Ce,Cerio,58,140.12 20 | Th,Torio,90,232.038 21 | Ti,Titanio,22,47.9 22 | Zr,Zirconio,40,91.22 23 | Hf,Hafnio,72,178.49 24 | V,Vanadio,23,50.942 25 | Nb,Niobio,41,92.906 26 | Ta,Tántalo,73,180.94 27 | Cr,Cromo,24,51.996 28 | Mo,Molibdeno,42,95.94 29 | W,Tungsteno,74,183.85 30 | Mn,Manganeso,25,54.938 31 | Tc,Tecnecio,43,98.9062 32 | Re,Renio,75,186.21 33 | Fe,Fierro,26,55.847 34 | Ru,Rutenio,44,101.07 35 | Os,Osmio,76,190.2 36 | Pr,Praseodimio,59,140.907 37 | Pa,Protactinio,91,229.0359 38 | Nd,Neodimio,60,144.24 39 | U,Uranio,92,238.029 40 | Pm,Prometio,61,145 41 | Np,Neptunio,93,237.0482 42 | Sm,Samario,62,150.4 43 | Pu,Plutonio,94,244 44 | Eu,Europio,63,151.96 45 | Am,Americio,95,243 46 | Gd,Gadolinio,64,157.25 47 | Cm,Curio,96,247 48 | Tb,Terbio,65,158.9254 49 | Bk,Berkelio,97,247 50 | Dy,Disprosio,66,162.5 51 | Cf,Californio,98,251 52 | Ho,Holmio,67,164.9304 53 | Es,Einstenio,99,254 54 | Er,Erbio,68,167.26 55 | Fm,Fermio,100,257 56 | Tm,Tulio,69,168.9342 57 | Md,Mendelevio,101,258 58 | Yb,Iterbio,70,173.04 59 | No,Nobelio,102,259 60 | Lu,Lutencio,71,174.96 61 | Lr,Lawrencio,103,260 62 | Rf,Rutherfordio,104,261 63 | Ha,Hahnio,105,262 64 | Co,Cobalto,27,58.9332 65 | Rh,Rodio,45,102.905 66 | Ir,Iridio,77,192.2 67 | Ni,Níquel,28,58.71 68 | Pd,Paladio,46,106.4 69 | Pt,Platino,78,195.09 70 | Cu,Cobre,29,63.54 71 | Ag,Plata,47,107.868 72 | Au,Oro,79,196.967 73 | Zn,Zinc,30,65.37 74 | Cd,Cadmio,48,112.4 75 | Hg,Mercurio,80,200.59 76 | B,Boro,5,10.811 77 | Al,Aluminio,13,26.9815 78 | Ga,Galio,31,69.72 79 | In,Indio,49,114.82 80 | Tl,Talio,81,204.37 81 | C,Carbono,6,12.01115 82 | Si,Silicio,14,28.086 83 | Ge,Germanio,32,72.59 84 | Sn,Estaño,50,118.69 85 | Pb,Plomo,82,207.19 86 | N,Nitrógeno,7,14.0067 87 | P,Fósforo,15,30.9738 88 | As,Arsénico,33,74.9216 89 | Sb,Antimonio,51,121.75 90 | Bi,Bismuto,83,208.96 91 | O,Oxígeno,8,15.9994 92 | S,Azufre,16,32.064 93 | Se,Selenio,34,78.96 94 | Te,Telurio,52,127.6 95 | Po,Polonio,84,209 96 | F,Flúor,9,18.998403 97 | Cl,Cloro,17,35.453 98 | Br,Bromo,35,79.904 99 | I,Yodo,53,126.9045 100 | At,Astato,85,210 101 | He,Helio,2,4.0026 102 | Ne,Neón,10,20.183 103 | Ar,Argón,18,39.948 104 | Kr,Kriptón,36,83.8 105 | Xe,Xenón,54,131.3 106 | Rn,Radón,86,222 107 | -------------------------------------------------------------------------------- /migrate_example_i18n.info.yml: -------------------------------------------------------------------------------- 1 | # Package info 2 | name: 'Migrate Example (multilingual)' 3 | description: Examples of multilingual migrations. 4 | type: module 5 | core: 8.x 6 | package: Examples 7 | 8 | # Dependencies 9 | dependencies: 10 | - drupal:system (>=8.3) 11 | - migrate 12 | - migrate_drupal 13 | - migrate_plus 14 | - migrate_tools 15 | - migrate_source_csv 16 | - node 17 | - taxonomy 18 | - content_translation 19 | -------------------------------------------------------------------------------- /migrate_example_i18n.install: -------------------------------------------------------------------------------- 1 | onConfigImporterImport(); 15 | } 16 | -------------------------------------------------------------------------------- /migrate_example_i18n.module: -------------------------------------------------------------------------------- 1 | handleTranslations($query); 41 | return $query; 42 | } 43 | 44 | /** 45 | * Adapt our query for translations. 46 | * 47 | * I copied this method from from the Drupal 6 node source 48 | * \Drupal\node\Plugin\migrate\source\d6\Node. Once the 49 | * "translations" parameter is supported in Drupal 7, we 50 | * would safely be able to remove this method. 51 | * 52 | * @param \Drupal\Core\Database\Query\SelectInterface $query 53 | * The generated query. 54 | */ 55 | protected function handleTranslations(SelectInterface $query) { 56 | // Check whether or not we want translations. 57 | if (empty($this->configuration['translations'])) { 58 | // No translations: Yield untranslated nodes, or default translations. 59 | $query->where('n.tnid = 0 OR n.tnid = n.nid'); 60 | } 61 | else { 62 | // Translations: Yield only non-default translations. 63 | $query->where('n.tnid <> 0 AND n.tnid <> n.nid'); 64 | } 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/Plugin/migrate/source/D7NodeEntityTranslation.php: -------------------------------------------------------------------------------- 1 | configuration['node_type'])) { 38 | return FALSE; 39 | } 40 | 41 | $variable = 'language_content_type_' . $this->configuration['node_type']; 42 | $translation = $this->variableGet($variable, 0); 43 | return $translation == self::ENTITY_TRANSLATION_ENABLED; 44 | } 45 | 46 | /** 47 | * {@inheritdoc} 48 | */ 49 | protected function handleTranslations(SelectInterface $query) { 50 | // If entity translations are not enabled, do nothing. 51 | if (!$this->isEntityTranslatable()) { 52 | return; 53 | } 54 | 55 | // Entity translation data is kept in the entity_translation table. 56 | $query->join('entity_translation', 'et', 57 | "et.entity_type = :entity_type AND et.entity_id = n.nid", 58 | [':entity_type' => 'node'] 59 | ); 60 | 61 | // Use only originals, or only translations, depending on our configuration. 62 | $operator = empty($this->configuration['translations']) ? '=' : '<>'; 63 | $query->condition('et.source', '', $operator); 64 | 65 | // A list of fields to override from the 'entity_translation' table. 66 | $override = [ 67 | 'language' => 'language', 68 | 'uid' => 'uid', 69 | 'status' => 'status', 70 | 'translate' => 'translate', 71 | 'created' => 'created', 72 | 'changed' => 'changed', 73 | 'vid' => 'revision_id', 74 | ]; 75 | $fields =& $query->getFields(); 76 | foreach ($override as $alias => $et_column) { 77 | unset($fields[$alias]); 78 | $query->addField('et', $et_column, $alias); 79 | } 80 | } 81 | 82 | /** 83 | * Adds additional data to the row. 84 | * 85 | * Overridden to pass the $language argument to getFieldValues(). 86 | * 87 | * @todo This should be supported by parent::prepareRow(). Once it is there, 88 | * we won't have to override the method. 89 | * 90 | * @param \Drupal\Migrate\Row $row 91 | * The row object. 92 | * 93 | * @return bool 94 | * FALSE if this row needs to be skipped. 95 | */ 96 | public function prepareRow(Row $row) { 97 | // Get field identifiers. 98 | foreach (array_keys($this->getFields('node', $row->getSourceProperty('type'))) as $field) { 99 | $nid = $row->getSourceProperty('nid'); 100 | $vid = $row->getSourceProperty('vid'); 101 | $language = $row->getSourceProperty('language'); 102 | // Get field values. 103 | $row->setSourceProperty($field, $this->getFieldValues('node', $field, $nid, $vid, $language)); 104 | } 105 | return FieldableEntity::prepareRow($row); 106 | } 107 | 108 | /** 109 | * Retrieves field values for a single field of a single entity. 110 | * 111 | * Overridden to support the $language argument, so that we can retrieve 112 | * values for a specific languages. 113 | * 114 | * @todo This should be supported by parent::prepareRow(). Once it is there, 115 | * we won't have to override the method. 116 | * 117 | * @param string $entity_type 118 | * The entity type. 119 | * @param string $field 120 | * The field name. 121 | * @param int $entity_id 122 | * The entity ID. 123 | * @param int|null $revision_id 124 | * (optional) The entity revision ID. 125 | * @param string|null $language 126 | * (optional) The language code. 127 | * 128 | * @return array 129 | * The raw field values, keyed by delta. 130 | */ 131 | protected function getFieldValues($entity_type, $field, $entity_id, $revision_id = NULL, $language = NULL) { 132 | $table = (isset($revision_id) ? 'field_revision_' : 'field_data_') . $field; 133 | $query = $this->select($table, 't') 134 | ->fields('t') 135 | ->condition('entity_type', $entity_type) 136 | ->condition('entity_id', $entity_id) 137 | ->condition('deleted', 0); 138 | if ($language) { 139 | $query->condition('language', $language); 140 | } 141 | if (isset($revision_id)) { 142 | $query->condition('revision_id', $revision_id); 143 | } 144 | $values = []; 145 | foreach ($query->execute() as $row) { 146 | foreach ($row as $key => $value) { 147 | $delta = $row['delta']; 148 | if (strpos($key, $field) === 0) { 149 | $column = substr($key, strlen($field) + 1); 150 | $values[$delta][$column] = $value; 151 | } 152 | } 153 | } 154 | return $values; 155 | } 156 | 157 | /** 158 | * {@inheritdoc} 159 | */ 160 | public function getIds() { 161 | $ids = parent::getIds(); 162 | if (!empty($this->configuration['translations']) 163 | && $this->isEntityTranslatable() 164 | ) { 165 | // With Entity Translation, each translation has the same node ID. 166 | // To uniquely identify a row, we therefore need both nid and 167 | // language. 168 | $ids['language'] = [ 169 | 'type' => 'string', 170 | 'alias' => 'et', 171 | ]; 172 | } 173 | return $ids; 174 | } 175 | 176 | } 177 | --------------------------------------------------------------------------------