JavaScript

时间:2015-04-29 08:34:33

标签: javascript

我是一名JavaScript新手,通过研究计算数学函数的 JavaScript“项目”来学习。这一切都运作良好。现在,作为进一步的步骤,我想使消息多语言。代码应该能够在运行时加载适当的语言文件。对于动态加载问题,我在this one等网页上阅读并找到了解决方案。

在编写动态代码之前,我静态加载它,测试代码运行良好。我要求帮助的代码只是加载“脚本”元素的细微差别。

我遇到问题的代码是 this.getString 函数,在该函数中无法访问语言文件中的 de 元素。在行 console.log(eval(language,tag)); ,我收到错误消息“ Uncaught ReferenceError:de is not defined ”。

//File: Utils/Lang/js/FileUtils.js
function Language(language) {
    var __construct = function(dynamicLoad) {
        if (typeof language == 'undefined') {
            language = "en";
        }
        // Load the proper language file:
        loadFile("js/resources/lang.de.js");
        return;
    } ()

    this.getString = function(tag, strDefault) {
        console.log("getString(" + tag + ", " + strDefault + "): ");
        console.log("getString(...): document = " + document);
        console.log("getString(...): eval(" + language + ", " + tag + ") = ");
        console.log(eval(language, tag));
        var strReturn = eval('eval(language).' + tag);

        if (typeof strReturn != 'undefined') {
            return strReturn;
        } else {
            return (typeof strDefault != 'undefined') 
                ? strDefault
                    : eval('en.' + tag);
        }
    }
}

不包括有效的静态测试代码,我可以访问de元素。

我的问题:如何正确加载语言文件以便可以访问 de 标记?

感谢您的帮助!

 //File: Utils/Files/js/FileUtils.js
 function loadFile(filepathname) {
     var reference = document.createElement('script');

     reference.setAttribute("type", "text/javascript");
     reference.setAttribute("src", filepathname);

     if (typeof reference != 'undefined') {
       document.getElementsByTagName("head")[0].appendChild(reference);
     }
     console.log("loadFile(\"" + filepathname + "\"): document = " + document);
   }
 //File: Utils/Lang/js/resources/lang.de.js:
 de = {
   pleaseWait: "Bitte warten..."
 };

 //File: Utils/Lang/js/resources/lang.en.js
 en = {
   pleaseWait: "Please wait..."
 };

 //File: Utils/Lang/js/TestLanguage.js:
 function output() {
   console.log("output()");
   var codes = ['de', 'en'];

   for (var i = 0; i < codes.length; i++) {
     var translator = new Language(codes[i]);

     var message = "output(): in " + translator.getLanguage() + ": ";

     message += translator.getString('pleaseWait');

     console.log(message);
   }
 }
<!--File: Utils/Lang/TestLang.html:-->
<!DOCTYPE html>
<html>

<head>
  <meta charset="ISO-8859-1">
  <title>Test languages</title>
  <script type="text/javascript" src="../Files/js/FileUtils.js"></script>

  <script type="text/javascript" src="js/Language.js"></script>
  <script type="text/javascript" src="js/TestLanguage.js"></script>
</head>

<body>
  <button name="outputButton" onclick="output();">Click</button>
  <br>Please press [F12] so that you can see the test results.
</body>

</html>

3 个答案:

答案 0 :(得分:3)

将脚本标记添加到文档时,不会同步加载它。您需要等待文件加载后才能使用其中的代码。

您可以重新设计代码以使用script.onload回调:

var reference = document.createElement('script');
// ...
reference.onload = function() {
  alert("Script loaded and ready");
};

但是对于这种情况,如果你没有很多语言字符串,你可能最好只是静态加载它们。

答案 1 :(得分:0)

如何动态加载脚本文件(最基本的版本,还有多个选项):

   function loadScriptFile(scriptPath, jsFile, callBack)
   {
       var scriptTag = document.createElement("script"); //creates a HTML script element
       scriptTag.language = "JavaScript"; //sets the language attribute
       scriptTag.type = "text/javascript";
       scriptTag.src = scriptPath + jsFile + ".js"; //the source
       if (callBack)
       {
            scriptTag.onload = callback; //when loaded execute call back
       }
       var scriptTagParent = document.getElementsByTagName("script")[0];
       if (scriptTagParent)
       {
                scriptTagParent.parentNode.insertBefore(scriptTag, scriptTagParent);
       }
       else
       {
           document.body.appendChild(scriptTag);
       }
    }

工作原理:

运行loadScriptFile("scripts", "math", startProgram)。前两个参数将指向您的文件和文件夹。最后一个参数是回调函数。定义后,一旦脚本标记完成加载并且脚本在全局范围内可用,将执行此操作。该脚本将动态添加到您的页面。如果页面上存在脚本元素,则会在此之前添加该脚本元素(以使标记保持良好)。如果不是它将被附加到身体。 (这只是视觉上的)。

回调部分是最有趣的。由于您的脚本现在将是 asynchronical ,因此您需要使用回调来告诉程序已加载必要的文件。加载脚本文件时会触发此回调,因此您不会收到脚本错误。

只是我在评论中的意思的基本示例:

  

这不是你问题的答案,它是一种替代方式(我认为管理更好)。纯Javascript(借助XML)

XML-file:language.xml 基本XML结构:

<language>
    <l1033 name="english" tag="en-US">
        <id1000>
            <![CDATA[
                Hello World!
            ]]>
        </id1000>
    </l1033>
    <l1031 name="german" tag="de-DE">
        <id1000>
            <![CDATA[
                Hallo Welt!
            ]]>
        </id1000>
    </l1031>
</language>

我做了什么:
我构造了一个名为language的根元素。在其中写了两个语言字符串,英语为l1033,德语为l1031。请注意,在语言代码之前添加了一个字母。当标记以数字开头时,XML将抛出错误。 CDATA块用于防止特殊字符出现任何问题。

现在加载将由AJAX完成:

var xmlLoader = new XMLHttpRequest();
xmlLoader.onreadystatechange = trackRequest; //event to track the request, with call back
xmlLoader.open("get", "language.xml", true); //set asynchronous to true
xmlLoader.send(null);

function trackRequest()
{
   if (this.status == 200 && this.readyState == 4) //all is good
   {
      globalLanguageFile = this.responseXML;
      startProgram(); //fictive function that starts your program
   }
}

现在加载了XML。如何从中加载字符串?

function loadLanguageString(code, id, fallback)
{
    var word = fallback;  
    if (globalLanguageFile.getElementsByTagName("l"+code).length > 0)
    {
        if (globalLanguageFile.getElementsByTagName("l"+code).[0].getElementsByTagName("id"+id).length > 0)
        {
            //found the correct language tag and id tag. Now retrieve the content with textContent.
            word = globalLanguageFile.getElementsByTagName("l"+code).[0].getElementsByTagName("id"+id)[0].textContent;
        }
    }

    return word; //when failed return fall back string
}

如何调用该函数:

loadLanguageString(1031, 1000, "Hello World!");

答案 2 :(得分:0)

我使用GarethOwen的信息找到了我的问题的正确答案。以下是我必须做的代码修改:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="ISO-8859-1">
		<title>Test languages</title>
		<script type="text/javascript" src="../Arrays/js/ArrayUtils.js"></script>
		<script type="text/javascript" src="../Files/js/FileUtils.js"></script>
		<script type="text/javascript" src="../Logic/js/LogicalUtils.js"></script>
		
		<script type="text/javascript" src="js/LanguageUtils.js"></script>
		<script type="text/javascript" src="js/TestLanguageUtils.js"></script>
	</head>
	<!-- body onload="load(null, '../Maths/js/resources')" -->
	<body onload="load();">
		<button onclick="output();">Click</button><br>
		Please press [F12] so that you can see the test results.
	</body>
</html>

  1. TestLanguage.html :增强了正文标记

    <body onload="load()">
    
  2. TestLanguage.js : 2A。现在添加了HTML页面请求的 load()函数:

    var gCodes = ['de', 'en', 'tr'];
    function load() {
        console.log("load()");
        for (var i = 0; i < codes.length; i++) {
            new Language(codes[i]);
        }
    }
    
  3. 2B。在输出()函数中使用全局 gCodes 变量

    1. Language.js :为了更好地测试整体,我通过更改函数语言中构造函数中的行,使函数语言中的代码更加精细一些(语言) to:

        // Load the proper language file:
        if (eval("gLoaded.indexOf('" + language + "') < 0")) {
          loadFile("js/resources/lang." + language + ".js");
          gLoaded[gLoaded.length] = language;
      }
      
    2. 感谢您的支持! : - )

      //Lang/js/Lang.js:
      "use strict";
      
      /**
       * Object for multilingual message handling.
       *
       * @param language
       */
      function Language(language) {
        var __construct = function(dynamicLoad) {
          if (typeof language == 'undefined') {
            language = "en";
          }
          // Load the proper language file:
          switch (language) {
            case "de":
              loadFile("js/resources/lang.de.js");
              break;
            case "tr":
              loadFile("js/resources/lang.tr.js");
              break;
            default:
              loadFile("js/resources/lang.en.js");
          }
          return;
        }()
      
        /**
         * Returns the language of that object.
         *
         * @returns The language
         */
        this.getLanguage = function() {
          var strLanguage;
      
          switch (language) {
            case "de":
              strLanguage = "German";
              break;
            case "tr":
              strLanguage = "Turkish";
              break;
            default:
              strLanguage = "English";
          }
          return strLanguage;
        }
      
        /**
         * Returns the language code of that object.
         *
         * @returns The language code
         */
        this.getString = function(tag, strDefault) {
          var strReturn = eval('eval(language).' + tag);
      
          if (typeof strReturn != 'undefined') {
            return strReturn;
          } else {
            return (typeof strDefault != 'undefined') ? strDefault : eval('en.' + tag);
          }
        }
      }
      
      //Lang/js/TestLang.js:
      "use strict";
      
      var gCodes = ['de', 'en', 'tr'];
      
      function load() {
        console.log("load()");
      
        for (var i = 0; i < gCodes.length; i++) {
          new Language(gCodes[i]);
        }
      }
      
      /**
       * Object for multilingual message handling.
       *
       * @param language
       */
      function output() {
          console.log("output()");
      
          for (var i = 0; i < gCodes.length; i++) {
            var translator = new Language(gCodes[i]);
      
            var message = "output(): in " + translator.getLanguage() + ": ";
      
            message += translator.getString('pleaseWait');
      
            console.log(message);
          }
        }
        //Utils/Files/js/FileUtils.js:
      "use strict";
      
      /**
       * Object with file utilities
       *
       * @param filepathname
       */
      function loadFile(filepathname) {
        var methodName = "loadFile(" + filepathname + "): "
        var reference = document.createElement('script');
      
        reference.setAttribute("type", "text/javascript");
        reference.setAttribute("src", filepathname);
      
        if (typeof reference != 'undefined') {
          document.getElementsByTagName("head")[0].appendChild(reference);
        }
      
        reference.onload = function() {
          console.log(methodName + "onload(): Language script loaded and ready!");
        }
      }

      这是控制台输出:

      Here is the output:
      load()
      loadFile(js/resources/lang.de.js): onload(): Language script loaded and ready!
      loadFile(js/resources/lang.en.js): onload(): Language script loaded and ready!
      loadFile(js/resources/lang.tr.js): onload(): Language script loaded and ready!
      output()
      output(): in German: Bitte warten...
      output(): in English: Please wait...
      output(): in Turkish: Lütfen bekleyiniz...
      loadFile(js/resources/lang.de.js): onload(): Language script loaded and ready!
      loadFile(js/resources/lang.en.js): onload(): Language script loaded and ready!
      loadFile(js/resources/lang.tr.js): onload(): Language script loaded and ready!