<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 14 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
@font-face
{font-family:Tahoma;
panose-1:2 11 6 4 3 5 4 4 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
margin-bottom:.0001pt;
font-size:12.0pt;
font-family:"Times New Roman","serif";}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:purple;
text-decoration:underline;}
p
{mso-style-priority:99;
mso-margin-top-alt:auto;
margin-right:0in;
mso-margin-bottom-alt:auto;
margin-left:0in;
font-size:12.0pt;
font-family:"Times New Roman","serif";}
span.EmailStyle18
{mso-style-type:personal-reply;
font-family:"Courier New";
color:windowtext;}
.MsoChpDefault
{mso-style-type:export-only;
font-size:10.0pt;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoNormal"><font size="2" face="Courier New"><span style="font-size:11.0pt;font-family:"Courier New""><o:p> </o:p></span></font></p>
<p class="MsoNormal"><font size="2" face="Courier New"><span style="font-size:11.0pt;font-family:"Courier New"">Hello!<o:p></o:p></span></font></p>
<p class="MsoNormal"><font size="2" face="Courier New"><span style="font-size:11.0pt;font-family:"Courier New""><o:p> </o:p></span></font></p>
<p class="MsoNormal"><font size="2" face="Courier New"><span style="font-size:11.0pt;font-family:"Courier New"">I would question the value of translating programmatic error messages. In a technical product with a relatively small user base (such as OpenStack),
the translation of error messages is counter-productive, I would argue. The reason is: How do you “google” for a solution to a problem you have or how do you discuss it online with others in the community? You’ll be lucky to find anyone in the world that has
the same issue and maybe has posted a solution to it, but now you also need to find someone who uses the same language setting or deal with on-the-fly translations in discussions which are also error prone.<o:p></o:p></span></font></p>
<p class="MsoNormal"><font size="2" face="Courier New"><span style="font-size:11.0pt;font-family:"Courier New""><o:p> </o:p></span></font></p>
<p class="MsoNormal"><font size="2" face="Courier New"><span style="font-size:11.0pt;font-family:"Courier New"">OpenStack is not Facebook or Twitter, it’s not a consumer or end-user service. OpenStack’s users are clearly very technical. I’m not a native English
speaker myself, but I’d think all of us working in this industry will speak enough English to get a rough idea of what an error will be about and how to ask for help online. In English.
<o:p></o:p></span></font></p>
<p class="MsoNormal"><font size="2" face="Courier New"><span style="font-size:11.0pt;font-family:"Courier New""><o:p> </o:p></span></font></p>
<p class="MsoNormal"><font size="2" face="Courier New"><span style="font-size:11.0pt;font-family:"Courier New"">Juergen<o:p></o:p></span></font></p>
<p class="MsoNormal"><font size="2" face="Courier New"><span style="font-size:11.0pt;font-family:"Courier New""><o:p> </o:p></span></font></p>
<p class="MsoNormal"><font size="2" face="Courier New"><span style="font-size:11.0pt;font-family:"Courier New""><o:p> </o:p></span></font></p>
<p class="MsoNormal"><font size="2" face="Courier New"><span style="font-size:11.0pt;font-family:"Courier New""><o:p> </o:p></span></font></p>
<div style="border:none;border-left:solid blue 1.5pt;padding:0in 0in 0in 4.0pt">
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"><b><font size="2" face="Tahoma"><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif";font-weight:bold">From:</span></font></b><font size="2" face="Tahoma"><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif""> Ying
Chun Guo [mailto:guoyingc@cn.ibm.com] <br>
<b><span style="font-weight:bold">Sent:</span></b> Friday, November 16, 2012 5:29 AM<br>
<b><span style="font-weight:bold">To:</span></b> OpenStack Development Mailing List<br>
<b><span style="font-weight:bold">Subject:</span></b> [openstack-dev] Translate REST API return message to a different language as log translation<o:p></o:p></span></font></p>
</div>
</div>
<p class="MsoNormal"><font size="3" face="Times New Roman"><span style="font-size:12.0pt"><o:p> </o:p></span></font></p>
<p><font size="2" face="Arial"><span style="font-size:10.0pt;font-family:"Arial","sans-serif"">Hi, all</span></font><br>
<br>
<font size="2" face="Arial"><span style="font-size:10.0pt;font-family:"Arial","sans-serif"">When fault happens, the REST API response messages will contain a string as an explanation. Currently, the string of explanation is translated based on server side locale.
I got a new requirement: to translate REST API response messages based on the requested language from client side.</span></font><br>
<br>
<font size="2" face="Arial"><span style="font-size:10.0pt;font-family:"Arial","sans-serif"">For example, if the client is in China and sends a request with a parameter "Accept-Language: zh-CN" in HTTP header, the explanation in the REST API response should
be translated into Chinese. If the client is in France and sends a request with a parameter "Accept-Language: fr-FR" in header, the explanation in the REST API response should be translated into French. Regardless of the response messages translation, the
log in server side will be translated based on server side locale setting.</span></font><br>
<br>
<font size="2" face="Arial"><span style="font-size:10.0pt;font-family:"Arial","sans-serif"">In order to fulfil this request, I think, the most difficult thing is to separate the logic of LOG and API response. Because currently, the API response will be written
to the LOG exactly as it is. (Refer to ResourceExceptionHandler.__exit__(self, ex_type, ex_value, ex_traceback) in
<font color="navy"><span style="color:navy">Nova/nova/api/openstack/wsgi.py</span></font>) But I need the response message in the language specified by client, and the LOG in the language specified by server locale.</span></font><br>
<br>
<font size="2" face="Arial"><span style="font-size:10.0pt;font-family:"Arial","sans-serif"">I have two solutions for this requirement.</span></font><br>
<br>
<font size="2" face="Arial"><span style="font-size:10.0pt;font-family:"Arial","sans-serif"">One is to maintain a map between server locale translation and client requested translation in gettextutils.py. When raising a webob.exc.HTTPException, still use the
server locale translation as the explanation, which will be written to log. When composing the response JSON message (Refer to Fault.__call__(self, req) in
<font color="navy"><span style="color:navy">Nova/nova/api/openstack/wsgi.py</span></font>), get the client requested translation from the map and put it in the response JSON object.</span></font><br>
<br>
<font size="2" face="Arial"><span style="font-size:10.0pt;font-family:"Arial","sans-serif"">The other is to remove log writing from API response logic, which means, removing the log statements in ResourceExceptionHandler.__exit__(self, ex_type, ex_value, ex_traceback)
in <font color="navy"><span style="color:navy">Nova/nova/api/openstack/wsgi.py</span></font>. Add explicit LOG statement before raising a webob.exc.HTTPException. For example:</span></font><br>
<br>
<font size="2" face="Arial"><span style="font-size:10.0pt;font-family:"Arial","sans-serif"">msg = _('Invalid is_public filter [%s]') % req.params['is_public'] </span></font><br>
<font size="2" face="Arial"><span style="font-size:10.0pt;font-family:"Arial","sans-serif"">raise webob.exc.HTTPBadRequest(explanation=msg)
</span></font><br>
<br>
<font size="2" face="Arial"><span style="font-size:10.0pt;font-family:"Arial","sans-serif"">will be changed to:</span></font><br>
<br>
<font size="2" face="Arial"><span style="font-size:10.0pt;font-family:"Arial","sans-serif"">msg = _gettext('Invalid is_public filter [%s]')</span></font><br>
<font size="2" face="Arial"><span style="font-size:10.0pt;font-family:"Arial","sans-serif"">LOG.error(_(msg) % req.params['is_public'])</span></font><br>
<font size="2" face="Arial"><span style="font-size:10.0pt;font-family:"Arial","sans-serif"">raise webob.exc.HTTPBadRequest(explanation=_(msg,req.get_accept_language()) % req.params['is_public'])
</span></font><br>
<br>
<font size="2" face="Arial"><span style="font-size:10.0pt;font-family:"Arial","sans-serif"">Method _gettext(string) will do nothing to the string, just for string extraction. Method _(msg) will be changed to accept the second parameter _(msg, locale).</span></font><br>
<br>
<font size="2" face="Arial"><span style="font-size:10.0pt;font-family:"Arial","sans-serif"">Please let me know your opinion to these two solutions. Which one do you prefer? Or do you have better solutions?</span></font><br>
<br>
<font size="2" face="Arial"><span style="font-size:10.0pt;font-family:"Arial","sans-serif"">Regards<br>
Ying Chun Guo (Daisy)<br>
China Standards and Open Source Team<br>
Emerging Technology Institute (ETI)<br>
IBM China Development Lab<br>
<a href="Tel:(86-10)82453491">Tel:(86-10)82453491</a><br>
Email: <a href="mailto:guoyingc@cn.ibm.com">guoyingc@cn.ibm.com</a><br>
Address: 1F Tower B, Diamond Building 19 Zhongguancun Software Park, <br>
8 Dongbeiwang West Road, Haidian District, Beijing, P.R.C.100193</span></font><o:p></o:p></p>
</div>
</div>
</body>
</html>