We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 6726
    • 7,075 Posts
    Nice thanks for this, I’ll test it and report !
      .: COO - Commerce Guys - Community Driven Innovation :.


      MODx est l'outil id
      • 10449
      • 956 Posts
      @manu

      can’t we use the makeUrl function to travel the tree and just replace the /lang/ with your $language?

      You could use the full URL: $url = $modx->makeUrl($id, ’’, ’’, ’full’);
      Then, do some simple substr() or regex to change domain.com/xx/ -> domain.com/yy/
      where xx or yy are your language abbreviations/codes.

      in fact, I did this once myself for a threelingual site, works like a charm.

      edit:
      something along the lines of:

      <?php
      
      // this would be our resulting string fetched via $modx->makeUrl($id, '', '', 'full');
      $here = "http://www.domain.com/en/news/sport/football/latest-results.html";
      
      // create array from URL:
      $ar = explode("/", $here);
      
      
      $de = $ar;
      $fr = $ar;
      $it = $ar;
      
      // third index is language indicator:
      $de[3] = 'de';
      $fr[3] = 'fr';
      $it[3] = 'it';
      
      $urlDE = implode("/", $de);
      $urlFR = implode("/", $fr);
      $urlIT = implode("/", $it);
      
      // just for testing... in modx, you'd probably use $modx->setPlaceholder()
      echo "original url = $here <br /><br />";
      echo "german: $urlDE <br />";
      echo "french: $urlFR <br />";
      echo "italian: $urlIT <br />";
      
      ?>
      

        • 36624
        • 535 Posts
        well, tanx ganeshXL for your piece of code.

        just to report my experience with the original tutorial :

        in fact the code here works ^^ with sub folder too... but all aliases must exist otherwise it break.
          CTRL+SHIFT+U - Clear Cache
          CTRL+SHIFT+H - Hiding Heft Panel
          CTRL+SHIFT+N - Fast Create Resource
          CTRL+ALT+P - Preview Recource (in edit resorce window)
          CTRL+ALT+S - Save
          • 31601
          • 57 Posts
          Hello, and thanks for this!

          I’m not sure if I’m doing something completely idiotic here, but I’ve followed this pretty much to the letter, and whenever I check the links for the language selection, the path inserts "minimal-base" instead of the appropriate alias.

          Any ideas? Thanks!

          OK, my bad- I hadn’t set the folders that contain the seperate language files to be shown in the menu- therefore the wayfinder call was going all the way to my old, non-published "Home" page and pulling it’s alias.

          Now, I have another problem- yep, this switches between the language pairs, but after switching from one language to another, the paths degenerate and eventually lead to non-existent pages. Scenario:

          I have two folders, english and french in the root of the directory structure. Two links are shown for choosing language: english and french. Start page in configuration is a page in the english folder.

          Click on the french link- the correct alias path is in the link, french page loads.
          Click on the english link- the correct alias path is in the link, english page loads.

          Here’s where it goes pear shaped:

          Hover over the link for either english or french, and the link points to the root language folder only in either language: running on an xampp server, path is localhost/modx/en or localhost/modx/fr. These folders have no content, but OK, I go ahead and click on one of these links. This is an error, by the way- the paths should still be pointing to the page that is currently loaded, correct? It seems that the alias for the document has completely disappeared after the alias for the parent language folder!

          Now the paths in the links are completely incorrect. Paths are now shown as localhost/modx/en/en or localhost/modx/fr/en

          I really want to deploy this solution, as I don’t want a packet of TV’s that end-users have to configure!

          Edit: figured this one out!

          When calling the snippet [[language]] in the first line of the template code cached, this error occurs! Simply calling the snippet uncached [!language!], and the problem goes away! You might want to make mention of this in your usage of this solution, aceman! Excellent solution, by the way- not too hard to document this for end users!
            • 349
            • 76 Posts
            Hi folks,

            tommorow i will publish a big update.

            I modified the complete logic, because some people on the german forum complained about the use of the alias field because it breaks the nature of speaking urls. So now i use the description field for my approach. I could do it with a template variable too, but maybe i post this later.

            What changed?
            The languageChooser points to the actual page in the corresponding languages.
            If the actual page can´t be found in the other language it will take you to the root of the language.
            So no more 404s if you switch the language and the page doesn´t exist.
            You now can have unique aliases for every page.

            This is the old version. Look at first post for the actual version.

            Multilingual Websites with MODx

            After reading the solutions in this forum, none of them convinced me. I wanted that the user stays on the same page if he switches the language.

            But i didn´t want to assign the relation between the languages via a template variable. It should function automatic.

            So i found a solution for myself. It performs well, but surely has potential for improvements.
            Comments and improvements are welcome. Hope my solution helps someone.

            Update
            I found out that my solution couldn´t handle subfolders in the language folder. Too bad that my site needs subfolders. So i rewrote the main snippet "language" from scratch. Now I have a very good solution and even a 404 error page, that shows a sitemap in your selected language. If the language can´t be determined, it will show the default language of your site (defined in configuration/site root).

            Changes between the previous version are:
            Put the snippet [[language]] in the first line of your template.
            Add the placeholder [+language+] where you need it. For example if you have different images in your languages.
            A brandnew 404 error page
            Placeholder "[+debugMsg+]" for tracing the language snippet
            End Update

            Here we go:
            EDIT:
            1. Modify your configuration under Tools/Configuration

            Use the following settings:
            friendly URLs: yes
            Use friendly aliases: yes
            Use friendly alias path: yes
            Allow duplicate aliases: yes

            2. build Site Tree
            First make a new folder and name it with your main language as the title. For example „english“, „deutsch“, „français“.
            This is what a visitor sees to set his language.
            The alias for this folder is a two-letter ISO Country Code that you can find here: http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm

            Now you create your pages as you would normally and give them an alias. After that you duplicate the whole folder for your next language and change the title and the country code in the alias field.
            The alias of the pages in your language folders is always the same. So if the first page has the alias „home“, the name in every other language is also „home“!!!

            Example:
            english / alias: en / type: folder
             |-> Welcome / alias: home (2)
            deutsch / alias: de / type: folder
             |-> Willkommen / alias: home (3)


            Now under configuration "set Site start": enter the id of the first page of your main language (2 in this example)

            3. create snippets
            Snippet Name: „language“.
            Description: creates placeholders and stores the actual language
            <?php
            
            // Placeholders set by this 
            $debugMsg = '$language is: '.$language.'<br />';
            $debugMsg = 'LanguageID from cookie: '.$_COOKIE['LanguageID'].'<br />';
            $params['topLevel'] =1;
            $aliasPath = '';
            
                // Regular Page
                // find Ultimate Parent of this page. The alias of this page sets the language variable
                if ($modx->config['error_page'] != $modx->documentIdentifier){
                    $up = $modx->runSnippet("UltimateParent", $params);
                    $tv = $modx->getTemplateVar('alias', "", $up);
                    $language = $tv['value'];
                    setcookie("Language",$language,time()+604800, "/", "", 0);
                    // LanguageID is needed for the 404 error page, to show the sitemap in the actual language
                    setcookie("LanguageID",$up,time()+604800, "/", "", 0);
                    $modx->setPlaceholder('LanguageID',$up);
                    $aliasPath = str_replace($language.'/','/',$modx->virtualDir.'/[*alias*]');
                }
                else{
                    // If Error Page
                    $debugMsg .= '<p>Error Page Start<br />';
            
                    if ( !empty ($_COOKIE['LanguageID'])){
                        $debugMsg .='$language is empty, try to read from cookie';
                        $language = $_COOKIE['Language'];
                        $LanguageID = $_COOKIE['LanguageID'];
                        $params['id'] = $LanguageID;
                        $up = $modx->runSnippet("UltimateParent", $params);
                        //setcookie("LanguageID",$up,time()+604800, "/", "", 0);
                        $modx->setPlaceholder('LanguageID',$up);
                    }
                    else {
                        $debugMsg .= '<p>LanguageID Cookie is empty, get ID from Site start</p>'.$modx->config['site_start'];
                        $params['id'] = $modx->config['site_start'];
                        $up = $modx->runSnippet("UltimateParent", $params);
                        //setcookie("LanguageID",$up,time()+604800, "/", "", 0);
                        $modx->setPlaceholder('LanguageID',$up);
                    }
                }
            
            $debugMsg .= 'LanguageID at finish: [+LanguageID+]<br />';
            
            $debugMsg .= '$aliasPath: '.$aliasPath.'<br />';
            $modx->setPlaceholder('aliasPath', $aliasPath);
            
            $debugMsg .= '$language: '.$language.'<br />';
            $modx->setPlaceholder('debugMsg', $debugMsg);
            
            $modx->setPlaceholder('language', $language);
            if (file_exists("assets/languages/$language.php")) include "assets/languages/$language.php";
            ?>


            Snippet "languageInclude" is no longer needed

            Snippet Name: „LanguageChooser“
            Description: „shortcut for the wayfinder“
            <?php
            echo '[!Wayfinder?&startId=0&level=1&rowTpl=LanguageRow&titleOfLinks=alias!]';
            ?>

            The titleOfLinks=alias sends the two-letter-language-code to the LanguageRow Snippet.

            create ChunkUpdate
            Chunk Name: „LanguageRow“
            Description: „prints a flag and the name of the language as a list item“
            Content:
            <li class="category [+wf.classnames+]"><a href="[(site_url)][+wf.title+][+aliasPath+]"><img src="[(base_url)]/assets/images/flags/gif/[+wf.title+].gif" alt="[+wf.linktext+]" /></a> <a href="[(site_url)][+wf.title+][+aliasPath+]" >[+wf.linktext+]</a>[+wf.wrapper+]</li>



            4. modify Site-TemplateUpdate
            Now you insert the follwing code in your template:
            inf first row of your template insert the placeholder "[[language]]"
            <div id="languageselection">
            [[LanguageChooser]]
            </div>
            <div id="navigation">
            [!Wayfinder? &startId=`[[UltimateParent]]`!]
            </div>
            

            This includes the languageChooser and the php-file in the actual language. And you get a navigation with only the sites in the selected language.

            5. Download Icons

            This is an optional step. However, if you skip this step, you will need to change the "LanguageRow" snippet below.


            • Download a set of icons whose names correspond to a two-letter Country Code and extract the folder to assets/images/flags
              you get nice looking flags from here: http://www.famfamfam.com/lab/icons/flags/
            • Make a directory assets/languages

            6. Forms
            Open the language file under assets/snippets/eform/lang and add your variables to it

            	$_lang['yourname'] = "Your Name";
            

            You can add as many variables as you need.

            Now you have to assign those variables to the fields array:
            Create a new snippet „setPrompts“
            <?php
            function setPrompts(&$fields) {
            global $_lang;
            $fields['yourname'] = $_lang['yourname'];
            return true;
            }
            ?>

            When you create your form chunk you have access to all the placeholders that you defined in the setPrompts snippet:

            [+validationmessage+]
            <form method="post" action="[~[*id*]~]">
                <input type="hidden" name="formid" value="feedbackForm" />
                <label for="cf[+yourname+]">[+yourname+]: </label>
            <input name="Your Name" id="cf[+yourname+]" class="required text" type="text" eform="[+yourname+]::1:" />
            

            Now insert your form on your contact page with the following code:
            [[setPrompts]]
            
            [!eForm? &formid=`feedbackForm` &to=`[email protected]`&eFormOnBeforeFormMerge=`setPrompts` &language=`german` &subject=`Web site feedback`!]
            


            Most important are the parameters „&language = `german`“ (name needs to be the same as in the assets/snippets/eform/lang folder) and „eFormOnBeforeFormMerge=`setPrompts`“ !

            Multilingual 404 Error Page
            Create a new folder in MODx that is unpublished.
            Then create and publish a new page with the title "[+errorpage+]" in it.
            Alias: "404"
            [[language]]
            [+errorpage+]
            [!Wayfinder? &startId=`[+LanguageID+]` &showDescription=`1`!]
            
            Now in your assets/languages/en.php (enter your 2 letter-language-code), add the following:
            <?php
            $modx->setPlaceholder("errorpage",'404 - Page not found');
            ?>
            <br />Translate this message for all of your languages and insert it in the language files.<br /><br />Your 404 error page is done and provides a sitemap in the actual language.<br />If the user selects a language for a page, that isn´t yet published for that language, he will be redirected to the 404-page in the selected language.<br /><br />[b]Thats it. Please comment.[/b]
              • 16545
              • 358 Posts
              Is it possible to modify your snippet to construct non dublicated language structures, I mean without en, de, jp directories....
              There are some reasons to do it before revolution will handle it.

              1) For web sites with more than ~ 100 (or even more than 50) documents too difficully to make changes in several documents places, worst thing if you must do it for more than 2 languages.
              2) Document consolidation
              3) Great solution for MODx community.

              Thx
                • 18108
                • 24 Posts
                HI. Thak you for this tutorial.
                However, I am not sure how to use the TV languageIdentifier.
                Can you explain it a little more please.
                Thanks in advance
                  Thank you for Modx, and thank you for your help.
                  • 349
                  • 76 Posts
                  Oh it´s really simple. If you have a page "contact" you type in the name "contact" in the languageIdentifier TV in every language for this page. This is how my snippet knows wich is the corresponding page in the other languages.
                    • 14491
                    • 15 Posts
                    Thanks for the great tutorial!

                    Make sure to note that for the language menu to function, ’Show in menu’ has to be enabled for the root folders for each language. Otherwise wayfinder won’t produce anything!
                      • 17010
                      • 20 Posts
                      Thanks for this. I was in desperate need of a multilingual solution. I’ve got my site set up and running properly, except for one thing, ditto is not working right alongside the multilingual stuff.

                      Ditto always adds a double language identifier to the links it produces. For instance it produces "http://mysite.com/us/us/FAQs/name.html"

                      I’m also learning ditto as I go, but an example call I am using is:

                      [!Ditto? &parents=`392`&sortBy=`title` &display=`all` &depth=`2` &summarize=`10` &showPublishedOnly=`1` &tpl=`faqtpl`!]

                      where my menu structure is like:

                      |-> English / alias: us / Type: folder (270)
                      |-> Welcome /alias: Welcome (389)
                      |-> FAQs /alias: FAQs (392)
                      |-> Name /alias: name (393)

                      Just to clarify, Wayfinder does do the links correctly from the startpage on through all the levels (i.e. &level=`3`).

                      How can I fix this?