We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 15001
    • 697 Posts
    I’m making some bilingual site with MODx with this basic structrure :
    root
      |
      fr--french documents
      |
      de--german documents

    There have been many discussion about multilingual sites.
    However, my site is simpler than most multilingual sites as it is only bilingual.
    Then, I plan to use a "translation" T.V. in each document, storing the id of the translation.

    For bilingual sites, it would be perfect if when duplicating a top-level folder (in my case "fr" duplicated to "de"), MODx’s manager asked if folder should be duplicated as translation, and in this case :
    1) ask the language code of the translation ("de" in my case)
    2) automatically set the "translation" T.V. value of all duplicated nodes/documents with the id of the original node.
    3) automatically set the "translation" T.V. value of all original nodes/documents with the id that is given to the copies.

    I currently do not have experience in hacking the core of MODx.
    Is hacking the core a difficult task ?
    Any idea which files should I look at ?
      • 20413
      • 2,877 Posts
      Link fields together so their values always match

      http://modxcms.com/ManagerManager-1565.html

      //havent installed and tried this yet.
        @hawproductions | http://mrhaw.com/

        Infograph: MODX Advanced Install in 7 steps:
        http://forums.modx.com/thread/96954/infograph-modx-advanced-install-in-7-steps

        Recap: Portland, OR (PDX) MODX CMS Meetup, Oct 6, 2015. US Bancorp Tower
        http://mrhaw.com/modx_portland_oregon_pdx_modx_cms_meetup_oct_2015_us_bancorp_tower
        • 9130
        • 171 Posts
        You might want to take a look at my multi-language snippet:
        http://modxcms.com/forums/index.php/topic,25827.0.html

        It relies on the document paths/aliases tree structure to automatically decide which pages a translation of each other and does not require manually setting a translation TV on every page.
          • 15001
          • 697 Posts
          Thanks for your answers.

          @mrhaw : I cannot see how I would use ManagerManager in this case, but I must aknowledge that I have not explored in detail what it can do exactly.

          @etal : Thanks for this complete multilingual solution. Your snippet has the benefit that one have to set the aliases once only (i.e. for the original documents) and the (future) translations inherit from it during the document duplication process.

          I also appreciate the fact that it accepts more than 2 languages, and the fact that it can downgrade to linking the homepage if no translation exists. This can be useful. An improvement could be also allowing downgrading to translated homepage.

          If I understood your approach, one drawback is that one have to set the alias manually for all documents of the original language. And another small drawback is the url which cannot be optimized for each language for the search engines.

          I had a new idea for a flexible multilingual site and I’ll try it :

          1) Create a T.V. in the template that stores and the same "document id" to all translation of the same document.
          Let’s call this T.V. "doc_id".

          2) Set "doc_id" to the same value as "id" for all documents (before original docs are duplicated).
          I think that this could be done with some batch SQL request.

          3) Duplicate the root node from the original language (i.e. add a translation).
          The values of "doc_id" of the translated docs would remain the same as those from the original document.

          4) Use some code that allows to link documents with the same "doc_id".

          To know the language of each document, I plan to use either regular expression applied to search-engine-friendly URLs, or store it in a "language" T.V.
          Setting the "language" T.V. can be done at a glance for each language root by using the DocManager module.
            • 15001
            • 697 Posts
            2) Set "doc_id" T.V. to the same value as "id" for all documents (before original docs are duplicated).
            Well. I’m at step 2.
            I hope to be on the right way with my idea of a batch SQL request. undecided

            Who can help me setting up the SQL request ?
            From what I saw in phpMyAdmin, it seems that the document identifiers are stored in the site_content table.

            Now, for each document in the original language, it is necessary to create a new record in table site_templvar_contentvalues to store the value for TV doc_id, which must take the id of the document.

            In my case, the doc_id TV is numbered 22 in MODx. (see code below)

            Can someone help me converting the pseudocode below into a true SQL request that I can run from phpMyAdmin ?

            Pseudocode :
            FOR EACH id FROM mydb_site_content
              BEGIN
                INSERT INTO mydb_site_templvar_contentvalues 
                   VALUES (AutoIncrementedId, 22, mydb_site_content.id, mydbsite_content.id)
              END

            How to create an (autoincremented) id for the new row ?
            Need to also update other tables ?

            Thanks for any help.
              • 15001
              • 697 Posts
              To insert a new row in table mydb_site_templvar_contentvalues, I think that the SQL request will be more or less this :
              INSERT INTO mydb_site_templvar_contentvalues VALUES (DEFAULT, 22, mydb_site_content.id, mydbsite_content.id)

              Could some experimented MySQL user tell me how to insert such record for each MODx document stored in the site_content table ?

              Can I describe loops in SQL or is PHP absolutely necessary for this ?


                • 15001
                • 697 Posts
                I’m going to try this PHP script.
                This should set the doc_id TV to the same value as id for each document.
                <?php
                   
                /* include connexion parameters */
                require("param.inc.php");
                
                /* connect the MySql server */
                $connexion = mysql_connect($server, $login, $password) or
                die("Impossible to connect server $server");
                
                /* connect the database */
                mysql_select_db($db) or die("Impossible to connect the $bd database");
                
                /* select identifiers of all MODx documents */
                $table = "mydbsite_content";
                $request= "SELECT id FROM $table";
                $result = mysql_query($request);
                
                while ($id = mysql_fetch_row($result) )  /* for each document */
                $table = "mydb_site_templvar_contentvalues";
                // 22 is here the number of the TV the document identifier shared by all translations of the document
                // for the document with id $id, set value for TV #22 to $id.
                $request= "INSERT INTO $table VALUES (DEFAULT, 22, $id, $id)";
                
                mysql_close($connexion);
                
                ?>
                  • 9130
                  • 171 Posts
                  My snippet already falls back on the appropriate language homepage if a matching page cannot be found. As for the url limitation, you are right, urls must be the same for all languages which isn’t great for SEO.

                  Now for your sql, sql does not have loops because loops are not needed. I’m no sql expert but I’ll give it my best shot:

                  First in phpMyAdmin find the id of the ’doc_id’ template variable in the ’modx_site_tmplvars’ table, for this example lets say its 22.

                  Then the sql should be something like:
                  INSERT INTO modx_site_tmplvar_contentvalues
                  (tmplvarid, contentid, value)
                  SELECT 22, id, id FROM modx_site_content


                  Replace the ’22’ with the appropriate number for your TV.
                  Note that I have NOT tested this statement, please backup your DB before running it.
                    • 15001
                    • 697 Posts
                    Thanks.

                    Not an expert in SQL, but I’m perplex about your syntax here,
                    SELECT 22, id, id FROM modx_site_content

                    as in the _site_content table, there is no column name with the number of the TV.

                    I think that I’m close to get it work. I corrected some small errors in my PHP script.
                    Now, it connects to the database and the requests do not produce any error.

                    However, nothing is updated in table _site_templvar_contentvalues; like if the result from the first request returned no documents identifiers.
                    Any idea about what’s wrong ?

                    <?php
                    // Don't forget to set manually the 2nd VALUE 
                    // in the INSERT INTO request with the number or the TV to update.
                    // Also set the correct MODx database prefix at the beginning or the table names.
                       
                    /* include connexion parameters */
                    require("db_connexion_params.inc.php");
                    
                    /* connect the MySql server */
                    $connexion = mysql_connect($server, $login, $password) or
                    die("Impossible to connect server $server");
                    echo "$server server connected<br>";
                    
                    /* connect the database */
                    mysql_select_db($db) or die("Impossible to connect the $bd database");
                    echo "$db database connected<br>";
                    
                    /* select identifiers of all MODx documents */
                    $table = "dbprefix_site_content";
                    $request= "SELECT id FROM $table";
                    $result = mysql_query($request);
                    
                    // WHAT FOLLOWS DOES NOT WORK AS TABLE alti_site_templvar_contentvalues IS NOT UPDATED
                    // STRANGELY, NO ERROR IS DISPLAYED. LIKE IF THEY WERE NO ROWS IN $result
                    
                    $table = "dbprefix_site_templvar_contentvalues";
                    while ($id = mysql_fetch_row($result) ) { /* for each document */
                      $request= "INSERT INTO $table VALUES (DEFAULT, 22, $id, $id)";
                    // 22 is here the number of the TV the document identifier shared by all translations of the document
                    // for the document with id $id, set value for TV #22 to $id.
                    }
                    
                    echo "Closing MySQL connexion<br>";
                    mysql_close($connexion) or die("Impossible to close the MySQL connexion.");
                    echo "MySql connexion closed.";
                    
                    ?>


                    File db_connexion_params.inc.php is like this :
                    <?php
                    $server="localhost";
                    $login="root";
                    $password="";
                    $db="mydatabase";
                    ?>


                    I was careful and saved my db before running any PHP/MySQL code. Good advice.
                      • 9130
                      • 171 Posts
                      Not an expert in SQL, but I’m perplex about your syntax here,
                      SELECT 22, id, id FROM modx_site_content

                      as in the _site_content table, there is no column name with the number of the TV.

                      This is valid sql syntax, you can run it on its own and see what it returns.