javascriptdjangomultilingualdjango-multilingual

Loading Scripts Conditionally with JS for multilingual django app that uses jquery validation plugin


I have a Django form in which I use the Jquery Validation Plugin to validate. My form needs to appear in multiple languages and I allow the user to change the form language on the click of a button (one button for each possible language). There is a separate script to load for each language to allow for built-in validation messages to show up in that language. For example, if I want default validation messages from this plugin to be in Russian, I would load the "https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.1/localization/messages_ru.min.js" script.

My questions are as follows:

  1. Should I really be just appending new scripts to the header section as I do below? Then, if the user clicks back and forth on language buttons, there are going to be a bunch of scripts in my DOM that are completely unnecessary and are just overridden by the last script loaded. Is this problematic? Bad style? Is there a better way to do this?
  2. I'm not sure what to do if they click on the 'English' button because in that case, I have to get rid of all of the other language scripts so that it defaults to English. Is there an easy way to go about doing this? I thought of going through all of the children of header and taking out all of the last ones until I get back up to bootstrap (which is my last one before these scripts), but then if I or someone else chooses to add another script on the end over there, this code will be messed up...

Maybe there's some way to have a specific space in the header that is reserved for these scripts and I can just replace or remove what's in that space based on what button the user clicks?

  1. Is there some way to use a variable within the script source? They're all exactly the same besides the two letters that specify the language, so I feel that my code is very redundant.
  2. I'm also not sure exactly how to pass in the element that has been clicked to my ChangeValidationLanguage method.

The js code that I have so far in order for the proper script to be loaded based on a button click is this:

window.onload = function() {
document.getElementsByClassName('btn-outline-secondary').setAttribute('onclick', "ChangeValidationLanguage()");
};

function ChangeValidationLanguage(element) {
         var head = document.getElementsByTagName('head')[0];
         var js = document.createElement("script");

         js.type = "text/javascript";
        if (element.id === '#form_ru') {
            js.src = "https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.1/localization/messages_ru.min.js";
        }
        else if (element.id === '#form_fr'){
            js.src = "https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.1/localization/messages_fr.min.js";
        }
        else if (element.id === '#form_es'){
            js.src = "https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.1/localization/messages_es.min.js";
        }
        else if (element.id === '#form_he'){
            js.src = "https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.1/localization/messages_he.min.js";
        }
        // else{ //if (element.id === '#form_en')
        //     js.src = ""
        // }

        head.appendChild(js);


     }

My buttons in html look like this:

    <div class="language-buttons">       
          <form action="/i18n/setlang/" method="post" id="form_en" style="display:inline!important;">
          <input type="hidden" name="csrfmiddlewaretoken" value="...">
            <input name="next" type="hidden" value="" />
            <input name="language" type="hidden" value="en" />
          </form>
          <a><button class="btn-outline-secondary" type="submit" form="form_en" value="Submit">English </button></a>

          <form action="/i18n/setlang/" method="post" id="form_ru" style="display:inline!important;">
          <input type="hidden" name="csrfmiddlewaretoken" value="...">
            <input name="next" type="hidden" value="" />
            <input name="language" type="hidden" value="ru" />
          </form>
          <a><button class="btn-outline-secondary" type="submit" form="form_ru" value="Submit">Русский </button></a>

          <form action="/i18n/setlang/" method="post" id="form_fr" style="display:inline!important;">
          <input type="hidden" name="csrfmiddlewaretoken" value="...">
            <input name="next" type="hidden" value="" />
            <input name="language" type="hidden" value="fr" />
          </form>
          <a><button class="btn-outline-secondary" type="submit" form="form_fr" value="Submit">français </button></a>

          <form action="/i18n/setlang/" method="post" id="form_es" style="display:inline!important;">
          <input type="hidden" name="csrfmiddlewaretoken" value="...">
            <input name="next" type="hidden" value="" />
            <input name="language" type="hidden" value="es" />
          </form>
          <a><button class="btn-outline-secondary" type="submit" form="form_es" value="Submit">español </button></a>

          <form action="/i18n/setlang/" method="post" id="form_he" style="display:inline!important;">
          <input type="hidden" name="csrfmiddlewaretoken" value="...">
            <input name="next" type="hidden" value="" />
            <input name="language" type="hidden" value="he" />
          </form>
          <a><button class="btn-outline-secondary" type="submit" form="form_he" value="Submit">עברית </button></a>

    </div>

Thank you!


Solution

  • Ok. Instead of using Javascript(since Sparky above advised against it), I did the following:

    Step 1: In my views.py I created a function to give return the proper language script based on a given language code:

    def getLangScript(language_code='en'):
        if language_code == 'ru':
            lang_script = "https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.1/localization/messages_ru.min.js"
        elif language_code == 'fr':
            lang_script = "https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.1/localization/messages_fr.min.js"
        elif language_code == 'es':
            lang_script = "https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.1/localization/messages_es.min.js"
        elif language_code == 'he':
            lang_script = "https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.1/localization/messages_he.min.js"
        else:
            lang_script = ""
        return lang_script
    

    Step 2: I changed my views to accept a language code as a parameter, with English being the default in case no parameter is passed. I call my above function to get the proper script, and then pass that script in to the context so I have access to it in my template:

    def post_list(request, language_code='en'):
    .
    .
    .
    lang_script = getLangScript(language_code)
    return render(request, 'template.html', {'form': form, 'lang_script': lang_script})
    

    Step 3: I changed my path in urls.py to accept a url parameter, which will be the language code (i.e. 'en' for English):

    urlpatterns = [
        .
        .
        .
    
        path('test/<str:language_code>/', views.post_list, name='post_list'),
    ]
    

    Step 4: In my template, I added <script src="{{ lang_script }}"></script> where I wanted the script to be loaded that would cause my validations to appear in a different language (I have access to it from my context).

    Step 5: (Here is the exciting part!) In the input element with the name "next", I passed in the url that I want it to redirect to WITH the language.code parameter. Based on this parameter that will be passed to the view, the view will call my getLangScript function, figure out which script to load, and then pass that script to the template as a context variable. See below.

    <div class="language-buttons">
            {% get_current_language as LANGUAGE_CODE %}
            {% get_available_languages as LANGUAGES %}
            {% get_language_info_list for LANGUAGES as languages %}
            {% for language in languages %}
              <form action="{% url 'set_language' %}" method="post" id="form_{{ language.code }}" style="display:inline!important;">
              {% csrf_token %}
                <input name="next" type="hidden" value="{% url 'post_list' language.code%}" />
                <input name="language" type="hidden" value="{{ language.code }}" />
              </form>
              <a><button class="btn-outline-secondary" type="submit" form="form_{{ language.code }}" value="Submit">{{ language.name_local}} </button></a>
            {% endfor %}
        </div>
    

    In this way, when the user clicks the button, the proper script will be loaded into the DOM and the validation messages from jquery language plugin will show up in the correct language!!

    If anyone has further comments about whether this was a wise way to do this or if there are better ways, I would be interested.