通过 XMLHttpRequest 将 gettext 与 PHP 中的 Javascript 一起使用

Posted

技术标签:

【中文标题】通过 XMLHttpRequest 将 gettext 与 PHP 中的 Javascript 一起使用【英文标题】:Using gettext with Javascript from PHP via XMLHttpRequest 【发布时间】:2018-03-10 16:05:49 【问题描述】:

我有一个主要用 php 编写的应用程序。翻译是使用 gettext() 完成的。

有一个小的 javascript 部分也包含要翻译的字符串。 我使用 XMLHttpRequest 编写了这个简单但有效的方法:

function gettext(string_to_translate) 
    var filename = get_php_script_folder() + 'gettext.php?string_to_translate=' + string_to_translate;
    var xmlhttp = new XMLHttpRequest();
    xmlhttp.open("GET", filename, false);
    xmlhttp.send();
    if (xmlhttp.status === 200) 
        var translated_string = xmlhttp.responseText;
        return translated_string;
     else 
        console.log("Error while translating " + string_to_translate + " Status " + xmlhttp.status);
        return string_to_translate; //Just give the original string.
    


php文件也很简单:

require_once '../../default.php'; //configures gettext, session management, etc.
//TODO: support for ngettext might be added.
$string_to_translate = filter_input(INPUT_GET, 'string_to_translate', FILTER_SANITIZE_STRING);
$translated_string = gettext($string_to_translate);
echo $translated_string;

在我刚刚调用的 JavaScript 中:

var input_box_form_default_reason = gettext("Vacation");
document.getElementById('input_box_form_reason').value = input_box_form_default_reason;

如果我同步调用此函数 [xmlhttp.open("GET", filename, false);] Firefox/Chrome 会警告我:

[Deprecation] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.

因此,尽管此方法有效,但它可能随时停止。

但如果我运行代码 async [xmlhttp.open("GET", filename, true);],那么下一行将在结果出现之前执行。该值将是未定义的。

在这种情况下使异步 XMLHttpRequest 工作是否可行?在编写一些聪明的 API 之前,我是否应该坚持同步获取值? 我应该用 PHP 编写我的 JS 文件吗? (我希望不会。)

PS:

    我不使用任何像 jQuery 这样的框架。这是一个“宗教”的事情。我想自己完全理解和维护整个代码库。

    我阅读了以下问题,但没有回答我的问题:

    Translation in JavaScript like gettext in PHP?

    PHP Gettext in JavaScript, not working in extern JS file

    Extract javascript gettext in Poedit?

    How do I feed terms from a gettext dictionary into JavaScript?

    javascript i18n with gettext and .po files(链接失效)

【问题讨论】:

我个人使用 PHP 在页面源代码中直接填充需要翻译的任何字符串的 JS 数组,不依赖任何 AJAX 请求。如果您有很多字符串,那么您还会查看大量请求,这可能会降低您的应用速度。 我同意。我加载了一个带有翻译的 xml 文件,并使用 xpath 将它们读出。 【参考方案1】:

是的,您需要回电!

function gettext(string_to_translate, obj, callback)
... //your original xmlhttprequest
xmlhttp.callback = callback;, add a callback to the xmlhttp

//set the readystate event that listens to changes in the ajax call
xmlhttp.onreadystatechange = function()

    //target found and request complete
    if (this.status === 200 && this.readyState == 4) 
        //send result to the callback function
        this.callback(obj, this.responseText);
     else 
        console.log("Error while translating " + string_to_translate + " Status " + xmlhttp.status);
        this.callback(obj, string_to_translate);
    


//callback function specific for this case.
function setValue(obj, value)

   obj.value = value;

这样称呼:

gettext("Vacation", document.getElementById('input_box_form_reason'), setValue);

带有回调的扩展ajax函数

function ajax(url, method, json, callBack)

	//it supports get and post
	//returns parsed JSON, when json is set to true. | json accessible via this.JSON in the callBack
	//a callback can be attached where the this refers to the xmlHTTP
	//supply an url like you would in a get request: http://www.example.com/page.php?query=1
	//start the request with xmlDoc.fire.
	
	var xmlDoc = new XMLHttpRequest
	xmlDoc.JSON = json ? true : false;
	xmlDoc.error = true;
	xmlDoc.errorMessage = "";	
	xmlDoc.errorObj = "error" : xmlDoc.error, "object" : "XMLHttpRequest", "message" : xmlDoc.errorMessage, "url" : url, "sync" : true, "method" : (method ? "POST" : "GET");
	xmlDoc.url = url
	xmlDoc.method = method ? "post" : "get";
	
	xmlDoc.preserveWhiteSpace = true;

	if (method == "post")
	
		xmlDoc.pUrl = url; 
		xmlDoc.pArg = "";
		if (url.match(/\?/)) //we need to filter out the arguments since the are send seperately. 
		
			var splitted = url.split(/\?/);
			xmlDoc.pUrl = splitted[0];
			xmlDoc.pArg = "";
			for (var i = 1; i < splitted.length; i++)
			
				xmlDoc.pArg += splitted[i];	//prevent additional questionmarks from being splitted.				
								
			
		
		
		xmlDoc.open.apply(xmlDoc, ["post", xmlDoc.pUrl , true]); //set up the connection
		
		xmlDoc.setRequestHeader("Content-type", "application/x-www-form-urlencoded ; charset=UTF-8");
	
	else
	
		//get request, no special action need, just pass the url
		this.xmlDoc.open("get", url, true); //true for async
	

	xmlDoc.onreadystatechange = readyStateXML.bind(xmlDoc, callBack);
	xmlDoc.setRequestHeader("Pragma", "no-cache");
	xmlDoc.setRequestHeader("Cache-Control", "no-cache, must-revalidate");
	
	xmlDoc.fire = fireXmlRequest; //set up fire function.
	
	return xmlDoc;


function fireXmlRequest()

	if (this.method == "post")
	
		this.send(this.pArg); //post
	
	else
	
		this.send(null); //get
	


function readyStateXML(callBack)

	if (this.readyState == 4)
	
		//request completed, now check the returned data
		//We always assume that a request fails.
		if (this.errorMessage == "XML Not loaded." || this.errorMessage == "")
		
			this.error = false; //set error to false, request succeeded.
			this.errorObj.error = false;			

			if (!this.responseXML && !this.JSON)
			
				this.error = true;
				this.errorMessage = "invalid XML.";
				this.errorObj.error = this.error;
				this.errorObj.message = this.errorMessage;				
			
			
			if (this.error == false)
			
				this.xmlData = this.responseXML;
				
				if (this.JSON)
				
					try
					
						this.JSON = JSON.parse(this.responseText);
					
					catch(err)
					
						//JSON couldn't be parsed
						this.error = true;
						this.errorMessage = err.message + "<br />" + this.responseText;
						this.errorObj.error = this.error;
						this.errorObj.message = this.errorMessage;		
					
				
				
			
			
			//404 or 400, not found error
			if (this.status == "400" || this.status == "404" || this.status == 400 || this.status == 404)
			
				this.error = true;
				this.errorMessage = "404: The requested page isn't found.";
				this.errorObj.error = this.error;
				this.errorObj.message = this.errorMessage;				
			
			else if(this.status == "500")
			
				this.error = true;
				this.errorMessage = "500: Internal server error.";
				this.errorObj.error = this.error;
				this.errorObj.message = this.errorMessage;				
			

			if (typeof(callBack) != "undefined")
			
				callBack.call(this); //pass the xmlDoc object to the callBack
			
		
		else
		
			alert("Error \n" + this.errorMessage);
			if (typeof(callBack) != "undefined")
			
				callBack.call(this);
			
		
			
	
	else
	
		this.error = true;
		this.errorMessage = "XML Not loaded.";
		this.errorObj.error = this.error;
		this.errorObj.message = this.errorMessage;		
	


//to use
ajx = ajax("index.php?query=1", "post", true, false, function()/*callback*/);
   console.log(ajx);
   ajx.fire();

【讨论】:

谢谢!我只是做了一些小改动:link【参考方案2】:

JS 是一种事件驱动的编程语言。您缺少的是在您的请求完成时触发的事件。您可以将事件“onreadystatechange”绑定到您的 xmlhttp 对象,该对象将在每次readyState 更改时触发。

function gettext(string_to_translate) 
var filename = get_php_script_folder() + 'gettext.php?string_to_translate=' + string_to_translate;
var xmlhttp = new XMLHttpRequest();

xmlhttp.onreadystatechange = function() 
    if (xmlhttp.status === 200) 
        var translated_string = xmlhttp.responseText;
        document.getElementById('input_box_form_reason').value = translated_string;
     else 
        console.log("Error while translating " + string_to_translate + " Status " + xmlhttp.status);
    
;
xmlhttp.open("GET", filename);
xmlhttp.send();

我建议阅读有关 JS 事件和回调的内容。

【讨论】:

【参考方案3】:

正如 Mouser 所指出的,需要有回调。 我编辑了我的函数如下:

function gettext(string_to_translate, object, callback_function) 
    var filename = get_php_script_folder() + 'gettext.php?string_to_translate=' + string_to_translate;
    var xml_http_request = new XMLHttpRequest();

    /*
     * Default values:
     */
    if (undefined === callback_function) 
        callback_function = set_value;
    
    /*
     * Input error handling:
     */
    if (typeof object !== "object") 
        console.log("Error:" + object + " is not an object.");
        return false;
    
    if (typeof callback_function === "function") 
        xml_http_request.callback = callback_function; // add a callback to the xml_http_request
     else 
        console.log("Error:" + callback_function + " is not a function.");
        return false;
    

    xml_http_request.onreadystatechange = function ()
    
        //target found and request complete
        if (this.status === 200 && this.readyState === 4) 
            //send result to the callback function
            this.callback(object, this.responseText);
         else if (this.readyState === 4) 
            console.log("Error while translating " + string_to_translate + " Status " + xml_http_request.status);
            this.callback(object, string_to_translate);
        
    ;
    xml_http_request.open("GET", filename, true);
    xml_http_request.send();

//callback function specific for gettext
function set_value(object, value)

    object.value = value;

可以这样调用:

gettext("Vacation", document.getElementById('input_box_form_reason'));

“假期”是要翻译的字符串,input_box_form_reason 是要更改值的对象。为了在分配中更加灵活,可以修改 set_value 函数。对于复杂的文本翻译和拼接,gettext.php 需要优化。

【讨论】:

以上是关于通过 XMLHttpRequest 将 gettext 与 PHP 中的 Javascript 一起使用的主要内容,如果未能解决你的问题,请参考以下文章

仅仅通过Ajax(XMLHttpRequest)请求,能否将cookie保存到游览器上?

通过 XMLHttpRequest 从 JavaScript 向 PHP 发送数据

无法通过XMLHttpRequest发送大型json数据--javascript

如何使用 GET 方法通过 XMLHttpRequest 传递 FormData

ruby Gett媒体基准测试

使用 XMLHttpRequest 将多个文件上传到 Express.js 3.5 服务器