<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Miguel Alho - Multimédia</title>
	<atom:link href="http://miguelalho.com/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://miguelalho.com</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Sun, 29 Aug 2010 17:56:06 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Internacionalização de ficheiros de JavaScript</title>
		<link>http://miguelalho.com/?p=1151</link>
		<comments>http://miguelalho.com/?p=1151#comments</comments>
		<pubDate>Sun, 29 Aug 2010 17:43:05 +0000</pubDate>
		<dc:creator>Miguel Alho</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Informática]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[i18n]]></category>
		<category><![CDATA[l10n]]></category>
		<category><![CDATA[T4]]></category>

		<guid isPermaLink="false">http://miguelalho.com/?p=1151</guid>
		<description><![CDATA[Os últimos posts no meu blog têm sido acerca do tema da internacionalização de aplicações, nomeadamente:

ASP.Net – Método alternativo de internacionalização (i18n)
Localizar Enumerações
Adicionar novas línguas ao Windows (edições Home)

O post de hoje contínua o sobre o método alternativo com ASP.NET, recorrendo a ao GetText do GNU. Como vimos, a aplicação do método _() para substituir [...]]]></description>
			<content:encoded><![CDATA[<p>Os últimos posts no meu blog têm sido acerca do tema da internacionalização de aplicações, nomeadamente:</p>
<ul>
<li><a href="http://miguelalho.com/?p=1146" rel="bookmark" title="Permanent Link to ASP.Net – Método alternativo de internacionalização (i18n)">ASP.Net – Método alternativo de internacionalização (i18n)</a></li>
<li><a href="http://miguelalho.com/?p=1100" rel="bookmark" title="Permanent Link to Localizar Enumerações">Localizar Enumerações</a></li>
<li><a href="http://miguelalho.com/?p=1097" rel="bookmark" title="Permanent Link to Adicionar novas línguas ao Windows (edições Home)">Adicionar novas línguas ao Windows (edições Home)</a></li>
</ul>
<p>O post de hoje contínua o sobre o método alternativo com ASP.NET, recorrendo a ao <a href="http://www.gnu.org/software/gettext/manual/gettext.htm" target="_blank">GetText </a>do GNU. Como vimos, a aplicação do método _() para substituir texto localizável tornava-se um recurso simples e eficiente na internacionalização de ASP.NET. Em especial, é um método adoptado pela restantes linguagens e evita o esforço extra necessário para introduzir o texto em ficheiros .resx.</p>
<p>Procurei uma solução semelhante para Javascript, uma vez que a aplicação que estou a internacionalizar recorre muito a funcionalidade em javascript. Em especial, há mensagens de erro específicos e mensagens de confirmação contextualizadas. Especifico a ASP.Net, não encontrei nada de útil. Até achei muito estranho não detectar nada de muito útil nesse campo.</p>
<p>De qualquer forma, há alguns métodos genéricos a aplicar, incluíndo plugins em jQuery (<a href="http://plugins.jquery.com/project/gettext" target="_blank">http://plugins.jquery.com/project/gettext</a>), mas gostei da descrição dada em <a href="http://24ways.org/2007/javascript-internationalisation" target="_blank">24ways.org</a>. Simplesmente introduzi a função para _()  no meu ficheiro core de javascript (é uma pequena biblioteca e funções e abstracções comuns a todas as páginas das minhas aplicações, e incluído em todas as páginas):</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">function</span> _<span style="color: #009900;">&#40;</span>s<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span><span style="color: #009900;">&#40;</span>i18n<span style="color: #009900;">&#41;</span><span style="color: #339933;">!=</span><span style="color: #3366CC;">'undefined'</span> <span style="color: #339933;">&amp;&amp;</span> i18n<span style="color: #009900;">&#91;</span>s<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000066; font-weight: bold;">return</span> i18n<span style="color: #009900;">&#91;</span>s<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #000066; font-weight: bold;">return</span> s<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Com isto é esperado existir uma variável <em>i18n </em>definido com a lista de traduções em pares chave-valor em JSON, do tipo:</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #003366; font-weight: bold;">var</span> i18n <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span>
<span style="color: #3366CC;">&quot;&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;&quot;</span><span style="color: #339933;">,</span>
<span style="color: #3366CC;">&quot;Hello&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Olá&quot;</span><span style="color: #339933;">,</span>
<span style="color: #3366CC;">&quot;Goodbye&quot;</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Adeus&quot;</span><span style="color: #339933;">,</span>
<span style="color: #006600; font-style: italic;">//(...)</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>O método em 24ways.oprg refere ainda funções para formatar strings que podem ser uteis. Eu no entanto já tinha uma implementação de string.format para javascript (<a href="http://www.geekdaily.net/2007/06/21/cs-stringformat-for-javascript/" targte="_blank">http://www.geekdaily.net/2007/06/21/cs-stringformat-for-javascript/</a>).</p>
<p>Portanto, com a função no core, e a variável i18n adicionada, nos diversos ficheiros de javascript, onde fosse usado uma string, este deveria ser englobado por _():</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">confirm</span><span style="color: #009900;">&#40;</span>_<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'Confirma a alteração de estado nos processos seleccionados?'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #006600; font-style: italic;">//...</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Assim, quando executado, e porque o método _() está sempre presente, o texto será substituído pelo existente no dicionário ou se não encontrado, o próprio texto usado como argumento da função.</p>
<p>Resta apenas dois passos &#8211; gerar os ficheiros .po, que deve seguir um esquema semelhante ao mencionado no artigo de ASP.Net, usando instruções póst-build e o gettext, e depois transformar os registos dos ficheiros .po em json. O primeiro dos passos é relativamente directa, apenas necessitando de construir uma nova lista de ficheiros (apenas de .js) e adicionar as entradas envolvidas em _() no .pot. </p>
<p>O segundo passo é mais &#8220;dificil&#8221;. Não há nada para o fazer directamentem senão um script em perl (<a href="http://jsgettext.berlios.de/doc/html/po2json.html" target="_blank">http://jsgettext.berlios.de/doc/html/po2json.html</a>), e como não me servia, decidi construir um script T4 simples, para usar no processo. </p>
<p>O script assume alguns pressupostos, pelo que, se utilizar, deve de os ter em conta e alterar consoante o necessário. O primeiro é que os ficheiros resultantes, quer os .po, quer os .js vão estar cada um numa pasta dedicada à língua específica como por exemplo:</p>
<p>/Scripts/locale/xx/messages.po<br />
/Scripts/locale/xx/i18n.js</p>
<p>Também, considero que o ficheiro .po será gerado e unido com recurso a msgmerge, e portanto apenas devo transformar os ficheiros .po em ficheiros .js</p>
<p>Assim, o po2json.tt, colocado na pasta (/Scripts/locale/) pode ser executado após o build. Ele procurará o ficheiro .po de cada língua no array, e transformarará em um ficheiro i18n.js. Eu decidi definir as linguas manualmente, mas com pequenas alterações, podem ser detectadas automáticamente.</p>
<p>O T4 é o seguinte:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #008000;">&lt;</span><span style="color: #008080;">#@ Template Language=&quot;C#v3.5&quot; Hostspecific=&quot;True&quot; #&gt;</span>
<span style="color: #008000;">&lt;</span><span style="color: #008080;">#@ Output Extension=&quot;.js&quot; #&gt;</span>
<span style="color: #008000;">&lt;</span><span style="color: #008080;">#@ Import Namespace=&quot;System.IO&quot; #&gt;</span>
<span style="color: #008000;">&lt;</span><span style="color: #008080;">#@ Import Namespace=&quot;System.Collections.Generic&quot; #&gt;</span>
<span style="color: #008000;">&lt;</span><span style="color: #008080;">#@ Import Namespace=&quot;System.Text.RegularExpressions&quot; #&gt;</span>
<span style="color: #008000;">&lt;</span><span style="color: #008080;">#@ Include File=&quot;MultiOutput.t4&quot; #&gt;</span>
var i18n <span style="color: #008000;">=</span> <span style="color: #000000;">&#123;</span>
<span style="color: #008000;">&lt;</span><span style="color: #008080;">#</span>
    <span style="color: #FF0000;">string</span> localeFolderPath <span style="color: #008000;">=</span> <span style="color: #666666;">@&quot;D:\Codigo\ProjectoWeb\Scripts\locale\&quot;</span><span style="color: #008000;">;</span>
    <span style="color: #FF0000;">string</span><span style="color: #000000;">&#91;</span><span style="color: #000000;">&#93;</span> suportedLang <span style="color: #008000;">=</span> <span style="color: #000000;">&#123;</span><span style="color: #666666;">&quot;pt&quot;</span><span style="color: #000000;">&#125;</span><span style="color: #008000;">;</span>
    <span style="color: #FF0000;">string</span> pofileName <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;messages.po&quot;</span><span style="color: #008000;">;</span>
    <span style="color: #FF0000;">string</span> msgid <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;msgid&quot;</span><span style="color: #008000;">;</span>
    <span style="color: #FF0000;">string</span> msgstr <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;msgstr&quot;</span><span style="color: #008000;">;</span>
    <span style="color: #FF0000;">string</span> txtREGEX <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;<span style="color: #008080; font-weight: bold;">\&quot;</span>(.*)<span style="color: #008080; font-weight: bold;">\&quot;</span>&quot;</span><span style="color: #008000;">;</span>
&nbsp;
    <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span> lang <span style="color: #0600FF;">in</span> suportedLang<span style="color: #000000;">&#41;</span>
    <span style="color: #000000;">&#123;</span>
        <span style="color: #FF0000;">string</span><span style="color: #000000;">&#91;</span><span style="color: #000000;">&#93;</span> lines <span style="color: #008000;">=</span> File.<span style="color: #0000FF;">ReadAllLines</span><span style="color: #000000;">&#40;</span>localeFolderPath <span style="color: #008000;">+</span> <span style="color: #666666;">&quot;<span style="color: #008080; font-weight: bold;">\\</span>&quot;</span> <span style="color: #008000;">+</span> lang <span style="color: #008000;">+</span> <span style="color: #666666;">&quot;<span style="color: #008080; font-weight: bold;">\\</span>&quot;</span>  <span style="color: #008000;">+</span> pofileName<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        List<span style="color: #008000;">&lt;</span>KeyValuePair<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">string</span>, <span style="color: #FF0000;">string</span><span style="color: #008000;">&gt;&gt;</span> entries <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> List<span style="color: #008000;">&lt;</span>KeyValuePair<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">string</span>, <span style="color: #FF0000;">string</span><span style="color: #008000;">&gt;&gt;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #FF0000;">int</span> currentLine <span style="color: #008000;">=</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">;</span>
&nbsp;
        <span style="color: #0600FF;">while</span> <span style="color: #000000;">&#40;</span>currentLine <span style="color: #008000;">&lt;</span> lines.<span style="color: #0000FF;">Length</span><span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            <span style="color: #FF0000;">string</span> line <span style="color: #008000;">=</span> lines<span style="color: #000000;">&#91;</span>currentLine<span style="color: #000000;">&#93;</span><span style="color: #008000;">;</span>
            <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>line.<span style="color: #0000FF;">StartsWith</span><span style="color: #000000;">&#40;</span>msgid<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                <span style="color: #FF0000;">string</span> keyString <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;&quot;</span><span style="color: #008000;">;</span>
                keyString <span style="color: #008000;">+=</span> Regex.<span style="color: #0000FF;">Match</span><span style="color: #000000;">&#40;</span>line, txtREGEX<span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">Groups</span><span style="color: #000000;">&#91;</span><span style="color: #FF0000;">1</span><span style="color: #000000;">&#93;</span>.<span style="color: #0000FF;">Value</span><span style="color: #008000;">;</span>
&nbsp;
                <span style="color: #008080; font-style: italic;">//iterate while still a msgid</span>
                line <span style="color: #008000;">=</span> lines<span style="color: #000000;">&#91;</span><span style="color: #008000;">++</span>currentLine<span style="color: #000000;">&#93;</span><span style="color: #008000;">;</span>
                <span style="color: #0600FF;">while</span><span style="color: #000000;">&#40;</span>line.<span style="color: #0000FF;">StartsWith</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;<span style="color: #008080; font-weight: bold;">\&quot;</span>&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
                <span style="color: #000000;">&#123;</span>
                    keyString <span style="color: #008000;">+=</span> Regex.<span style="color: #0000FF;">Match</span><span style="color: #000000;">&#40;</span>line, txtREGEX<span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">Groups</span><span style="color: #000000;">&#91;</span><span style="color: #FF0000;">1</span><span style="color: #000000;">&#93;</span>.<span style="color: #0000FF;">Value</span><span style="color: #008000;">;</span>
                    line <span style="color: #008000;">=</span> lines<span style="color: #000000;">&#91;</span><span style="color: #008000;">++</span>currentLine<span style="color: #000000;">&#93;</span><span style="color: #008000;">;</span>
                <span style="color: #000000;">&#125;</span>
&nbsp;
                <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>line.<span style="color: #0000FF;">StartsWith</span><span style="color: #000000;">&#40;</span>msgstr<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
                <span style="color: #000000;">&#123;</span>
                    <span style="color: #FF0000;">string</span> valueString <span style="color: #008000;">=</span> <span style="color: #666666;">&quot;&quot;</span><span style="color: #008000;">;</span>
                    valueString <span style="color: #008000;">+=</span> Regex.<span style="color: #0000FF;">Match</span><span style="color: #000000;">&#40;</span>line, txtREGEX<span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">Groups</span><span style="color: #000000;">&#91;</span><span style="color: #FF0000;">1</span><span style="color: #000000;">&#93;</span>.<span style="color: #0000FF;">Value</span><span style="color: #008000;">;</span>
&nbsp;
                    <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span><span style="color: #008000;">++</span>currentLine <span style="color: #008000;">&lt;</span> lines.<span style="color: #0000FF;">Length</span><span style="color: #000000;">&#41;</span>
                    <span style="color: #000000;">&#123;</span>
                        line <span style="color: #008000;">=</span> lines<span style="color: #000000;">&#91;</span>currentLine<span style="color: #000000;">&#93;</span><span style="color: #008000;">;</span>
                        <span style="color: #0600FF;">while</span> <span style="color: #000000;">&#40;</span>line.<span style="color: #0000FF;">StartsWith</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;<span style="color: #008080; font-weight: bold;">\&quot;</span>&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
                        <span style="color: #000000;">&#123;</span>
                            valueString <span style="color: #008000;">+=</span> Regex.<span style="color: #0000FF;">Match</span><span style="color: #000000;">&#40;</span>line, txtREGEX<span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">Groups</span><span style="color: #000000;">&#91;</span><span style="color: #FF0000;">1</span><span style="color: #000000;">&#93;</span>.<span style="color: #0000FF;">Value</span><span style="color: #008000;">;</span>
                            line <span style="color: #008000;">=</span> lines<span style="color: #000000;">&#91;</span><span style="color: #008000;">++</span>currentLine<span style="color: #000000;">&#93;</span><span style="color: #008000;">;</span>
                        <span style="color: #000000;">&#125;</span>
                    <span style="color: #000000;">&#125;</span>
                    <span style="color: #008080; font-style: italic;">//add pair to entries list</span>
                    entries.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">new</span> KeyValuePair<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">string</span>, <span style="color: #FF0000;">string</span><span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span>keyString, valueString<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                <span style="color: #000000;">&#125;</span>     
            <span style="color: #000000;">&#125;</span>
&nbsp;
            currentLine<span style="color: #008000;">++;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #008080; font-style: italic;">//build outoput</span>
        <span style="color: #0600FF;">for</span><span style="color: #000000;">&#40;</span> <span style="color: #FF0000;">int</span> i <span style="color: #008000;">=</span> <span style="color: #FF0000;">0</span><span style="color: #008000;">;</span> i<span style="color: #008000;">&lt;</span> entries.<span style="color: #0000FF;">Count</span><span style="color: #008000;">;</span> i<span style="color: #008000;">++</span><span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            KeyValuePair<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">string</span>, <span style="color: #FF0000;">string</span><span style="color: #008000;">&gt;</span> entry <span style="color: #008000;">=</span> entries<span style="color: #000000;">&#91;</span>i<span style="color: #000000;">&#93;</span><span style="color: #008000;">;</span>
&nbsp;
<span style="color: #008080;">#&gt;</span>
<span style="color: #666666;">&quot;&lt;#=  entry.Key #&gt;&quot;</span> <span style="color: #008000;">:</span> <span style="color: #666666;">&quot;&lt;#= entry.Value #&gt;&quot;</span><span style="color: #008000;">&lt;</span><span style="color: #008080;">#=    i&lt;entries.Count-1 ? &quot;,&quot; : &quot;&quot; #&gt;</span>
<span style="color: #008000;">&lt;</span><span style="color: #008080;">#</span>
        <span style="color: #000000;">&#125;</span>  
    SaveOutput<span style="color: #000000;">&#40;</span>localeFolderPath <span style="color: #008000;">+</span> <span style="color: #666666;">&quot;<span style="color: #008080; font-weight: bold;">\\</span>&quot;</span> <span style="color: #008000;">+</span> lang <span style="color: #008000;">+</span> <span style="color: #666666;">&quot;<span style="color: #008080; font-weight: bold;">\\</span>&quot;</span>  <span style="color: #008000;">+</span> <span style="color: #666666;">&quot;i18n.js&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span> 
&nbsp;
    <span style="color: #000000;">&#125;</span>
<span style="color: #008080;">#&gt;</span>
<span style="color: #000000;">&#125;</span><span style="color: #008000;">;</span></pre></div></div>

<p>Procura cada &#8220;msgid&#8221; e processa as línguas seguintes convenientemente. Se houver erros, o processo será abandonado. O tt recorre ainda a um MultiOutput.t4, para gerar mais que um ficheiro a partir do .tt, convenientemente localizado. Não necessita de estar incluído no projecto (para não obrigar a incluir as dependências de TextTempleting).</p>
<p>Para incluir o ficheiro na lista de scripts a puxar, basta regista-lo no ScriptManager, no Page_Load da MasterPage :</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">ScriptManager.<span style="color: #0000FF;">RegisterClientScriptInclude</span><span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span>, <span style="color: #008000;">typeof</span><span style="color: #000000;">&#40;</span><span style="color: #FF0000;">string</span><span style="color: #000000;">&#41;</span>, <span style="color: #666666;">&quot;i18n&quot;</span>, Page.<span style="color: #0000FF;">ResolveUrl</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;~/Scripts/locale/&quot;</span> <span style="color: #008000;">+</span> lang <span style="color: #008000;">+</span> <span style="color: #666666;">&quot;/i18n.js&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span></pre></div></div>

<p>onde a variável lang é uma string com as letras da língua, para identificar a pasta onde será armazenado. Eu obtenho a a língua para a aplicação (transversal), mas outra possibilidade seria definir a língua pelas preferências do utilizador. Também, o caminho poderia ser proveniente de uma chave de configuração no web.config, se necessário.</p>
<p>Creio que está é uma solução simples, que pode, se necessário ser melhorado com mais funções (especialmente de formatações e plural / singular) como descrito no artigo do 24ways.org. Para já, esta é me suficiente.</p>
<p><a href='http://miguelalho.com/wp-content/uploads/2010/08/po2json.zip'>Download po2json t4</a></p>
]]></content:encoded>
			<wfw:commentRss>http://miguelalho.com/?feed=rss2&amp;p=1151</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ASP.Net &#8211; Método alternativo de internacionalização (i18n)</title>
		<link>http://miguelalho.com/?p=1146</link>
		<comments>http://miguelalho.com/?p=1146#comments</comments>
		<pubDate>Wed, 25 Aug 2010 00:41:32 +0000</pubDate>
		<dc:creator>Miguel Alho</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[i18n]]></category>
		<category><![CDATA[internactionalização]]></category>
		<category><![CDATA[l10n]]></category>

		<guid isPermaLink="false">http://miguelalho.com/?p=1146</guid>
		<description><![CDATA[A internacionalização de aplicações (internationalization &#8211; i18n) para posterior localização (localization &#8211; l10n) é um processo multi-passo, que envolve a detecção de texto que deve ser apresentado em múltiplas línguas, bem como a preparação da base de código para que o texto possa ser correctamente traduzido.
Cada tecnologia tem a sua própria forma de implementar mecanismos [...]]]></description>
			<content:encoded><![CDATA[<p>A internacionalização de aplicações (internationalization &#8211; i18n) para posterior localização (localization &#8211; l10n) é um processo multi-passo, que envolve a detecção de texto que deve ser apresentado em múltiplas línguas, bem como a preparação da base de código para que o texto possa ser correctamente traduzido.</p>
<p>Cada tecnologia tem a sua própria forma de implementar mecanismos que auxiliam a tradução. .Net recorre a recursos compilados na forma de ficheiros .resx . Os ficheiros .resx são de uma forma geral pares chave-valor, estruturados em XML, que são compilados para dlls carregados no inicio da aplicação.</p>
<p>Apesar de uma solução interessante, é extremamente tediante usa-los em ASP.Net. Com as bibliotecas de uma API, ok. O suporte a nível de código C# (ou VB ) torna o uso relativamente simples. Já com ASP.Net, não é possível dizer o mesmo. As razões estão bem descritas em &#8220;<a href="http://www.expatsoftware.com/articles/2010/03/why-internationalization-is-hopelessly.html" target="_blank">Why Internationalization is hopelessly Broken in ASP.Net</a>&#8220;, mas resumindo, tudo tem de ser controlos ASP.Net com o runat=&#8221;server&#8221;, não há suporte simplificado a texto estático (escrito directamente na página), a referência de chaves das strings obriga a inserir meta:resoursekey=&#8221;" em todas os controlos, e os ficheiros .resx não são facilmente legíveis por pessoal não técnico.</p>
<p>A alternativa? Seguir o método do &#8220;resto do mundo&#8221; e usar ficheiros de strings em formatos simplificados, nomeadamente os ficheiros .po. Quem já explorou um projecto open-source ou projectos aplicacionais com add-ins linguísticos, muito provavelmente já se cruzaram com este formato de ficheiros. São ficheiros de texto simples, com texto assoiado a uma chave (msgid) e texto associado à tradução (msgstr). Por exemplo:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">msgid &quot;Pesquisar Candidatos&quot;
msgstr &quot;Search Candidates&quot;</pre></div></div>

<p>De notar neste exemplo que a chave está em PT e a tradução em EN. Não é recomendado esta abordagem, uma vez que as línguas latinas tem acentos que não são óptimos para chaves.</p>
<p>Continuando, o uso de ficheiros .PO, noutras frameworks, é suportado por por uma função gettext(), onde é passo a chave (geralmente o próprio texto, na língua base) e retorna a versão traduzida, conforme as preferências de utilizador. Melhor, há geralmente uma forma simplificada da função escrito _(). Assim, cada string a analisar chama a função gettext(), obtendo a versão traduzida do texto. Bem mais simples que os .resx e meta:resourcekey do .NET.</p>
<h2>Usando Fairlylocal</h2>
<p>O <a href="http://www.fairtutor.com/fairlylocal/" target="_blank">FailyLocal </a> é um projecto opensource iniciado por Jason Kester, e que implementa a funcionalidade do gettext e ficheiros PO para ASP.Net. Como descrito no link do projecto, para pedir a tradução, na página basta utilizar:</p>

<div class="wp_syntax"><div class="code"><pre class="asp" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;%</span><span style="color: #006600; font-weight: bold;">=</span> _<span style="color: #006600; font-weight:bold;">&#40;</span><span style="color: #cc0000;">&quot;texto a traduzir&quot;</span><span style="color: #006600; font-weight:bold;">&#41;</span> <span style="color: #000000; font-weight: bold;">%&gt;</span></pre></div></div>

<p>ou no codebehind:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">controlo.<span style="color: #0000FF;">InnerHtml</span> <span style="color: #008000;">=</span> _<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;texto a traduzir&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span></pre></div></div>

<p>Tão simples e eficaz. Em termos de biblioteca, basta adicionar os ficheiros ao projecto da aplicação (têm de ser um projecto de aplicação web, em vez de um projecto de website, uma vez que o segundo não <a href="http://www.fairtutor.com/fairlylocal/fairlylocal-details#basepage" target="_blank">permite evento post-build, que o primeiro permite, e que constrói dinamicamente os ficheiros PO</a>).</p>
<p>Em termos de execução, os ficheiros PO são carregados no arranque da aplicação, para um dicionário estático em memória, onde depois são realizadas as consultas do gettext(). Neste caso, todas as paginas devem herdar de InternationalPage ou InternationalMaster (ou a página base da aplicação derivar destas) em vez de Page directamente, para que _() fique disponível.</p>
<p>Para as minhas necessidades, efectuei pequenas alterações. Primeiro, para facilitar o uso em mutlipos projectos, adicionai os ficheiros ao projecto da minha framework, para que tenha sempre disponível. Segundo, porque necessito de aceder aos métodos, quer para a página instanciada, quer quando estou a usar WebMethods, tornei a propriedade LanguageCode e o método _() static. Finalmente, porque necessito de definir a língua ao nível da aplicação e não para cada utilizador, modifiquei o getter de LanguageCode para obter o código de lingua directamente da thread, em vez da sessão do utilizador:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #FF0000;">string</span> LanguageCode
<span style="color: #000000;">&#123;</span>
   get
   <span style="color: #000000;">&#123;</span>
       <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>_languageCode <span style="color: #008000;">==</span> <span style="color: #0600FF;">null</span><span style="color: #000000;">&#41;</span>
       <span style="color: #000000;">&#123;</span>
           _languageCode <span style="color: #008000;">=</span> <span style="color: #000000;">System.<span style="color: #0000FF;">Threading</span></span>.<span style="color: #0000FF;">Thread</span>.<span style="color: #0000FF;">CurrentThread</span>.<span style="color: #0000FF;">CurrentUICulture</span>.<span style="color: #0000FF;">TwoLetterISOLanguageName</span>.<span style="color: #0000FF;">ToLower</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
	<span style="color: #000000;">&#125;</span>
	<span style="color: #0600FF;">return</span> _languageCode<span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
    set
    <span style="color: #000000;">&#123;</span>
	_languageCode <span style="color: #008000;">=</span> value<span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Incluíndo os scripts post-build, os ficheiros .PO são actualizados após cada build, podendo ser traduzidos de seguida, ou directamente ou recorrendo a programas como o <a href="http://www.poedit.net/index.php" target="_blank">Poedit</a>. Ferramentas como o <a href="http://pepipopum.dixo.net/" target="_blank">Pepipopum </a>permitem traduzir automaticamente (via Google translate API) o ficheiro PO. As chaves devem estar em inglês para funcionar correctamente.</p>
<p>Finalmente, convém referir que o sistema tem fallback automático para o texto da própria chave &#8211; se o testo não estiver traduzido no ficheiro .po, o texto a usar é o próprio argumento do _(), o que ajuda muito se tiver a internacionalizar uma aplicação já existente.</p>
<h2>Uma macro util</h2>
<p>Ainda assim, com esta simplificação, internacionalizar uma aplicação existente não deixa de ser um trabalho tediante. Localizar o texto a traduzir e envolver no método _() é &#8220;chato&#8221;.</p>
<p>Para ajudar, criei uma macro:</p>

<div class="wp_syntax"><div class="code"><pre class="vb" style="font-family:monospace;"><span style="color: #000080;">Public</span> Module GetTextSurrond
&nbsp;
    <span style="color: #008000;">'' surround text with &lt;%= _(&quot; and &quot;) $&gt;
</span>    <span style="color: #008000;">''
</span>    <span style="color: #000080;">Sub</span> ASPXSurround()
        <span style="color: #000080;">Dim</span> textSelection <span style="color: #000080;">As</span> EnvDTE.TextSelection
&nbsp;
        textSelection = DTE.ActiveDocument.Selection()
        textSelection.Text = <span style="color: #800000;">&quot;&lt;%= _(&quot;</span><span style="color: #800000;">&quot;&quot;</span> + textSelection.Text + <span style="color: #800000;">&quot;&quot;</span><span style="color: #800000;">&quot;) &quot;</span> <span style="color: #008000;">''%&gt;&quot;
</span>    <span style="color: #000080;">End</span> <span style="color: #000080;">Sub</span>
&nbsp;
<span style="color: #000080;">End</span> Module</pre></div></div>

<p>Associando esta Macro a um atalho de teclas, por exemplo Ctrl+G, Ctrl+T, ajudará a usar a macro, bastando seleccionar o texto e executar o comando (nos ficheiros .aspx).</p>
<h2>Conclusão</h2>
<p>Pela curta experiência que tenho com esta alternativa de tradução, não deixa de me parecer N vezes mais vantajoso que o uso de ficheiros .resx no ASP.Net.  Os ficheiros .PO são apenas strings, portanto para recursos binários outra estratégia deve ser adoptada.</p>
]]></content:encoded>
			<wfw:commentRss>http://miguelalho.com/?feed=rss2&amp;p=1146</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Localizar Enumerações</title>
		<link>http://miguelalho.com/?p=1100</link>
		<comments>http://miguelalho.com/?p=1100#comments</comments>
		<pubDate>Mon, 05 Jul 2010 23:46:19 +0000</pubDate>
		<dc:creator>Miguel Alho</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[enum]]></category>
		<category><![CDATA[enumeração]]></category>
		<category><![CDATA[globalization]]></category>
		<category><![CDATA[locale]]></category>
		<category><![CDATA[ToString()]]></category>

		<guid isPermaLink="false">http://miguelalho.com/?p=1100</guid>
		<description><![CDATA[Continuando no desafio de localizar a minha aplicação, estou agora a atacar as enumerações. Esta também é uma óptima oportunidade de efectuar algum refactoring às classes e estruturas existentes.
Parte das enumerações usadas são automaticamente escritas com uma estrutura que era óptima.. até agora. A aplicação é N-layer, dividido em camadas lógicas. Por enquanto, e porque [...]]]></description>
			<content:encoded><![CDATA[<p>Continuando no desafio de localizar a minha aplicação, estou agora a atacar as enumerações. Esta também é uma óptima oportunidade de efectuar algum refactoring às classes e estruturas existentes.</p>
<p>Parte das enumerações usadas são automaticamente escritas com uma estrutura que era óptima.. até agora. A aplicação é <em>N-layer</em>, dividido em camadas lógicas. Por enquanto, e porque ainda não foi necessário mais, mantém-se <em>monotier</em>. As camadas lógicas neste caso são UI, BLL (<em>Business Lógic Layer</em>) e DAL (<em>Data Access Layer</em>), mais os repositórios de dados. Comum a todas as camadas há duas bibliotecas &#8211; MAAPPFramework que é um conjuntos de classes base, interfaces base, e muitos helpers comuns a várias aplicações (O MAAPP significa Miguel Alho Application : D ) e a camada de BO (<em>Business Objects</em>) que inclui as classes conceptuais e DTOs (<em>Data Transfer Objects</em>) do domínio. Os objectos nesta biblioteca são &#8220;dummy objects&#8221;, no sentido que não tem funcionalidade (senão algumas ordenações e extensões). Apenas suportam dados e estão devidamente decoradas para serem serializadas. Esta biblioteca é transformada em dll e utilizada por todas as camadas. Esta arquitectura está muito bem exemplificado pelo Imar Spaanjars nos seus artigos <a href="http://imar.spaanjaars.com/416/building-layered-web-applications-with-microsoft-aspnet-20-part-1" target="_blank">Building Layered Web Applications with Microsoft ASP.NET 2.0</a>.</p>
<p>As enumerações que eu tinha incluíam sempre um valor numérico definido explicitamente (evitando súbitas alterações de referências para com a base de dados numa nova geração de código) e uma descrição com texto legível, em vez de um texto colado em CamelCase. um exemplo:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">namespace</span> <span style="color: #0600FF;">Namespace</span>.<span style="color: #0000FF;">BO</span>
<span style="color: #000000;">&#123;</span>
    <span style="color: #000000;">&#91;</span>Serializable<span style="color: #000000;">&#93;</span>  
    <span style="color: #0600FF;">public</span> <span style="color: #FF0000;">enum</span> EnumTipoContacto
    <span style="color: #000000;">&#123;</span>	
        <span style="color: #000000;">&#91;</span>Description<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;Telefone&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
	Telefone <span style="color: #008000;">=</span> <span style="color: #FF0000;">1</span>,
        <span style="color: #000000;">&#91;</span>Description<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;Telemóvel&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
        Telemovel <span style="color: #008000;">=</span> <span style="color: #FF0000;">2</span>,
        <span style="color: #000000;">&#91;</span>Description<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;Email&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
        Email <span style="color: #008000;">=</span> <span style="color: #FF0000;">3</span>,
        <span style="color: #000000;">&#91;</span>Description<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;Fax&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
        Fax <span style="color: #008000;">=</span> <span style="color: #FF0000;">4</span>,
        <span style="color: #000000;">&#91;</span>Description<span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;Outro Tipo de Contacto&quot;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#93;</span>
        Outro <span style="color: #008000;">=</span> <span style="color: #FF0000;">5</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>A descrição escrita como atributo, recorrendo ao <em>System.ComponentModel.DescriptionAttribute</em> permite em runtime ter uma versão legível do nome da enumeração, óptima para apresentação na UI, em vez do tipo valor devolvido pelo método <em>ToString()</em>. No exemplo em cima, O caso do &#8220;Outro&#8221; demonstra a possível diferença. Para obter os valores, na minha <em>framework</em> tenho um método numa <em>helper class</em> que permite obter o valor da descrição, bem como uma <em>extension method</em> para ajudar:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">public</span> <span style="color: #FF0000;">class</span> EnumDescription
<span style="color: #000000;">&#123;</span>
        <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #FF0000;">string</span> GetDescription<span style="color: #000000;">&#40;</span><span style="color: #FF0000;">Enum</span> value<span style="color: #000000;">&#41;</span>
        <span style="color: #000000;">&#123;</span>
            FieldInfo fieldInfo <span style="color: #008000;">=</span> value.<span style="color: #0000FF;">GetType</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>.<span style="color: #0000FF;">GetField</span><span style="color: #000000;">&#40;</span>value.<span style="color: #0000FF;">ToString</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            DescriptionAttribute<span style="color: #000000;">&#91;</span><span style="color: #000000;">&#93;</span> attributes <span style="color: #008000;">=</span> <span style="color: #000000;">&#40;</span>DescriptionAttribute<span style="color: #000000;">&#91;</span><span style="color: #000000;">&#93;</span><span style="color: #000000;">&#41;</span>fieldInfo.<span style="color: #0000FF;">GetCustomAttributes</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span><span style="color: #000000;">&#40;</span>DescriptionAttribute<span style="color: #000000;">&#41;</span>, <span style="color: #0600FF;">false</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #0600FF;">return</span> <span style="color: #000000;">&#40;</span>attributes.<span style="color: #0000FF;">Length</span> <span style="color: #008000;">&gt;</span> <span style="color: #FF0000;">0</span><span style="color: #000000;">&#41;</span> <span style="color: #008000;">?</span> attributes<span style="color: #000000;">&#91;</span><span style="color: #FF0000;">0</span><span style="color: #000000;">&#93;</span>.<span style="color: #0000FF;">Description</span> <span style="color: #008000;">:</span> value.<span style="color: #0000FF;">ToString</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
        <span style="color: #000000;">&#125;</span>
&nbsp;
        <span style="color: #008080; font-style: italic;">//(...)</span>
<span style="color: #000000;">&#125;</span>
&nbsp;
<span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #FF0000;">class</span> EnumExtension
<span style="color: #000000;">&#123;</span>
    <span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #FF0000;">string</span> GetDescription<span style="color: #000000;">&#40;</span><span style="color: #0600FF;">this</span> <span style="color: #FF0000;">Enum</span> e<span style="color: #000000;">&#41;</span>
    <span style="color: #000000;">&#123;</span>
         <span style="color: #0600FF;">return</span> EnumDescription.<span style="color: #0000FF;">GetDescription</span><span style="color: #000000;">&#40;</span>e<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
    <span style="color: #000000;">&#125;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Considerando que o código é gerado a partir de um modelo que controlo, é uma óptima solução, desde que localizado a uma definição linguística. Seria possível criar múltiplos atributos (costumizados) para suportar descrições localizadas, por exemplo, mas a manutenção e separação não me parece optimizado. Procurei outra solução que me permitiria utilizar ficheiros de recursos (.resx).</p>
<p>Uma das técnicas que encontrei parece simples e óptima. A descrição passa a ser definida no ficheiro de recursos, e a chave é o nome qualificado da enumeração. Optei pelo nome completo porque é me fácil de gerar com <em>T4</em>. Assim, a minha enumeração fica simplificada:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #000000;">&#91;</span>Serializable<span style="color: #000000;">&#93;</span>
<span style="color: #0600FF;">public</span> <span style="color: #FF0000;">enum</span> EnumTipoContacto
<span style="color: #000000;">&#123;</span>	
	Telefone <span style="color: #008000;">=</span> <span style="color: #FF0000;">1</span>,
        Telemovel <span style="color: #008000;">=</span> <span style="color: #FF0000;">2</span>,
        Email <span style="color: #008000;">=</span> <span style="color: #FF0000;">3</span>,
        Fax <span style="color: #008000;">=</span> <span style="color: #FF0000;">4</span>,
        Outro <span style="color: #008000;">=</span> <span style="color: #FF0000;">5</span>,
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>e o meu ficheiro .resx terá um conjunto de chaves valores qualificados, que pode ser localizado na versão do ficheiro para outra língua:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;">(...)
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;data</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;Namespace.BO.EnumTipoContacto.Telefone&quot;</span> <span style="color: #000066;">xml:space</span>=<span style="color: #ff0000;">&quot;preserve&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Telefone<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/data<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>  
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;data</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;Namespace.BO.EnumTipoContacto.Telemovel&quot;</span> <span style="color: #000066;">xml:space</span>=<span style="color: #ff0000;">&quot;preserve&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Telemóvel<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/data<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>  
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;data</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;Namespace.BO.EnumTipoContacto.Email&quot;</span> <span style="color: #000066;">xml:space</span>=<span style="color: #ff0000;">&quot;preserve&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Email<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/data<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>  
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;data</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;Namespace.BO.EnumTipoContacto.Fax&quot;</span> <span style="color: #000066;">xml:space</span>=<span style="color: #ff0000;">&quot;preserve&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Fax<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/data<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>  
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;data</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;Namespace.BO.EnumTipoContacto.Outro&quot;</span> <span style="color: #000066;">xml:space</span>=<span style="color: #ff0000;">&quot;preserve&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Outro Tipo / Desconhecido<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/data<span style="color: #000000; font-weight: bold;">&gt;</span></span></span> 
(...)</pre></div></div>

<p>Para obter o valor da chave, a operação é ligeiramente diferente:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> <span style="color: #FF0000;">string</span> GetLocalizedDescription<span style="color: #000000;">&#40;</span>EnumTipoContacto tipo<span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
      ResourceManager resources <span style="color: #008000;">=</span> <span style="color: #0600FF;">Namespace</span>.<span style="color: #0000FF;">BO</span>.<span style="color: #0000FF;">Properties</span>.<span style="color: #FF0000;">Enum</span>.<span style="color: #0000FF;">ResourceManager</span><span style="color: #008000;">;</span>
&nbsp;
      <span style="color: #FF0000;">string</span> resourceKey <span style="color: #008000;">=</span> <span style="color: #FF0000;">String</span>.<span style="color: #0000FF;">Format</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;{0}.{1}&quot;</span>, tipo.<span style="color: #0000FF;">GetType</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>, tipo<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
      <span style="color: #FF0000;">string</span> localizedDescription <span style="color: #008000;">=</span> resources.<span style="color: #0000FF;">GetString</span><span style="color: #000000;">&#40;</span>resourceKey<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
      <span style="color: #0600FF;">if</span> <span style="color: #000000;">&#40;</span>localizedDescription.<span style="color: #0000FF;">IsNullOrEmpty</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
           <span style="color: #0600FF;">return</span> tipo.<span style="color: #0000FF;">ToString</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
      <span style="color: #0600FF;">else</span>
           <span style="color: #0600FF;">return</span> localizedDescription<span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Neste exemplo, <em>tipo.GetType()</em> devolve <em>Namespace.BO.EnumTipoContacto</em>, permitindo construir a chave. é necessário ter em atenção que linha</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;">ResourceManager resources <span style="color: #008000;">=</span> <span style="color: #0600FF;">Namespace</span>.<span style="color: #0000FF;">BO</span>.<span style="color: #0000FF;">Properties</span>.<span style="color: #FF0000;">Enum</span>.<span style="color: #0000FF;">ResourceManager</span><span style="color: #008000;">;</span></pre></div></div>

<p>obriga-me a que a assemblagem gerada seja o <em>Namespace.BO.dll</em> e o ficheiro de recursos é o <em>Enum.resx</em> ou <em>Enum.xx.resx</em> onde <em>xx</em> representa o código cultural (&#8220;es&#8221;, por exemplo). Novamente, porque o meu código é em boa parte autogerado, tenho controlo sobre esse formato.</p>
<p>Outro método muito útil, para usar como <em>DataSource</em> para preencher <em>DropDownLists </em>e controlos do género é a seguinte:</p>

<div class="wp_syntax"><div class="code"><pre class="csharp" style="font-family:monospace;"><span style="color: #0600FF;">public</span> <span style="color: #0600FF;">static</span> List<span style="color: #008000;">&lt;</span>KeyValuePair<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">string</span>, <span style="color: #FF0000;">string</span><span style="color: #008000;">&gt;&gt;</span> GetDDLList<span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>
<span style="color: #000000;">&#123;</span>
            List<span style="color: #008000;">&lt;</span>KeyValuePair<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">string</span>, <span style="color: #FF0000;">string</span><span style="color: #008000;">&gt;&gt;</span> kvPairList <span style="color: #008000;">=</span> <span style="color: #008000;">new</span> List<span style="color: #008000;">&lt;</span>KeyValuePair<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">string</span>, <span style="color: #FF0000;">string</span><span style="color: #008000;">&gt;&gt;</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            ResourceManager resources <span style="color: #008000;">=</span> <span style="color: #0600FF;">Namespace</span>.<span style="color: #0000FF;">BO</span>.<span style="color: #0000FF;">Properties</span>.<span style="color: #FF0000;">Enum</span>.<span style="color: #0000FF;">ResourceManager</span><span style="color: #008000;">;</span>
&nbsp;
            <span style="color: #0600FF;">foreach</span> <span style="color: #000000;">&#40;</span><span style="color: #FF0000;">Enum</span> enumValue <span style="color: #0600FF;">in</span> <span style="color: #FF0000;">Enum</span>.<span style="color: #0000FF;">GetValues</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">typeof</span><span style="color: #000000;">&#40;</span>EnumTipoContacto<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
            <span style="color: #000000;">&#123;</span>
                <span style="color: #FF0000;">string</span> resourceKey <span style="color: #008000;">=</span> <span style="color: #FF0000;">String</span>.<span style="color: #0000FF;">Format</span><span style="color: #000000;">&#40;</span><span style="color: #666666;">&quot;{0}.{1}&quot;</span>, enumValue.<span style="color: #0000FF;">GetType</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>, enumValue<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                <span style="color: #FF0000;">string</span> localizedDescription <span style="color: #008000;">=</span> resources.<span style="color: #0000FF;">GetString</span><span style="color: #000000;">&#40;</span>resourceKey<span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
&nbsp;
                <span style="color: #0600FF;">if</span><span style="color: #000000;">&#40;</span>localizedDescription.<span style="color: #0000FF;">IsNullOrEmpty</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span>
                    kvPairList.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">new</span> KeyValuePair<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">string</span>, <span style="color: #FF0000;">string</span><span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span>enumValue.<span style="color: #0000FF;">ToString</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>, enumValue.<span style="color: #0000FF;">ToString</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
                <span style="color: #0600FF;">else</span>
                    kvPairList.<span style="color: #0000FF;">Add</span><span style="color: #000000;">&#40;</span><span style="color: #008000;">new</span> KeyValuePair<span style="color: #008000;">&lt;</span><span style="color: #FF0000;">string</span>, <span style="color: #FF0000;">string</span><span style="color: #008000;">&gt;</span><span style="color: #000000;">&#40;</span>enumValue.<span style="color: #0000FF;">ToString</span><span style="color: #000000;">&#40;</span><span style="color: #000000;">&#41;</span>, localizedDescription<span style="color: #000000;">&#41;</span><span style="color: #000000;">&#41;</span><span style="color: #008000;">;</span>
            <span style="color: #000000;">&#125;</span>
&nbsp;
            <span style="color: #0600FF;">return</span> kvPairList<span style="color: #008000;">;</span>
<span style="color: #000000;">&#125;</span></pre></div></div>

<p>Semelhante à anterior, permite obter uma lista de <em>KeyValuePairs </em>aceites como <em>DataSource </em>dos controlos.</p>
<p>Este foi, numa fase inicial, o tipo de estrutura que mais me preocupava, no sentido que os atributos poderiam complicar a globalização, e obrigar a um refactoring interno profundo. Felizmente, um simples <em>workaround </em>e <em>refactoring </em>evitou grandes mexidas. Também, porque nem os nomes dos métodos (nomeadamente o <em>GetDDLList</em>() ) nem os tipos de dados foram alterados, a camada superior continua a funcionar sem ter sido afectado.</p>
]]></content:encoded>
			<wfw:commentRss>http://miguelalho.com/?feed=rss2&amp;p=1100</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Adicionar novas línguas ao Windows (edições Home)</title>
		<link>http://miguelalho.com/?p=1097</link>
		<comments>http://miguelalho.com/?p=1097#comments</comments>
		<pubDate>Fri, 02 Jul 2010 16:53:10 +0000</pubDate>
		<dc:creator>Miguel Alho</dc:creator>
				<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[globalização]]></category>
		<category><![CDATA[local]]></category>
		<category><![CDATA[localização]]></category>
		<category><![CDATA[MUI]]></category>
		<category><![CDATA[Windows 7]]></category>
		<category><![CDATA[Windows Server 2008]]></category>

		<guid isPermaLink="false">http://miguelalho.com/?p=1097</guid>
		<description><![CDATA[Eu desenvolvo sobre Windows, sobre um Windows 7 Home Premium, para ser mais exacto. E ao longo do tempo tenho sofrido de alguns obstáculos oferecido pelas limitações da versão. A versão é a que veio com o PC, e pretendo puxá-lo até onde possível, antes de fazer um upgrade para um Business ou Ultimate (apesar [...]]]></description>
			<content:encoded><![CDATA[<p>Eu desenvolvo sobre Windows, sobre um Windows 7 Home Premium, para ser mais exacto. E ao longo do tempo tenho sofrido de alguns obstáculos oferecido pelas limitações da versão. A versão é a que veio com o PC, e pretendo puxá-lo até onde possível, antes de fazer um upgrade para um Business ou Ultimate (apesar das restantes máquinas &#8211; desktop &#8211; aqui do escritório estarem com o Ultimate).</p>
<p>Mas infelizmente ontem, deparei-me com um problema que demorou a tarde toda a perceber, e quando assim é, é geralmente algo do OS e nada óbvio. Contextualizando, estou numa fase de internacionalizar uma aplicação web de gestão de currículos e processos de recrutamento e selecção, que desenvolvi no ano passado (e ainda este ano). Foi grande sucesso junto da equipa de trabalho, pois permitiu acelerar em muito os processos de recrutamento, que dado o volume de candidaturas que lhes chegavam &#8211; dezenas de milhares em meio ano &#8211; era tediante e constrangedor. Felizmente, a app foi criada à medida da equipa e adaptado ao processo de trabalho, e resultou em pleno.</p>
<p>De qualquer forma, a app está a ser internacionalizado para suportar as acções em Espanha, e o processo de internacionalização tem os seus próprios desafios associados &#8211; a globalização da aplicação para não ter dependências directas da língua nem numeração, e a localização para corresponder a cada realidade, quer de linguagem, quer de informação (por exemplo as diferenças de moradas e códigos postais e informação regional).</p>
<p>Sei que esta fase trará alguns problemas de estrutura e configuração &#8211; umas mais complicadas que outras &#8211; e a primeira apareceu logo na base de dados. Para a aplicação, optei pelo suporte de dados em base de dados relacional, e a base escolhida foi o PostgreSQL. Tem óptimas capacidades de armazenamento, suporte a pesquisa em XML, indexação e pesquisa de texto livre com o tSearch2, e é OpenSource que também foi muito atractivo na escolha. </p>
<p>Quando se cria uma base de dados no Postgre, o único parâmetro obrigatório é o nome da base de dados. As restantes definições são preenchidas com os valores pré-definidos da instalação. As que condicionam a base e que só podem ser definidas na criação são o LC_COLLATE e o LC_CTYPE. A primeira &#8211; LC_COLLATE, determina a forma como são ordenadas as palavras e que pode variar de cultura para cultura. O mesmo para o LC_CTYPE que caracteriza os caracteres em termos de maiúsculas, minúsculas, e pontuação</p>
<p>O problema destes parâmetros são a dependência do OS para esta informação. Seria muito interessante se dependesse apenas da base de dados e os executáveis associados, mas na verdade esta informação vem do sistema operativo. Por defeito, o valor para as variáveis são o da definições do OS. O Windows Server 2008 permite que o utilizador possa configurar a sua conta para definições regionais e linguísticas diferentes e que podem ser acrescentados através de MUIs (Multilingual User Interface). O mesmo é possível nas versões do Business e Ultimate do Windows. Infelizmente, no Home Premium não é possível, sem alguns workarounds. </p>
<p>Como afecta a criação da base? Simples. Se não tiver as definições linguísticas instaladas na máquina, não posso criar a base de dados usando essas definições, apenas com as existentes. Para portuguese, e portanto com base na definição do OS, tenho quer para LC_CTYPE, quer para LC_COLLATE o valor:</p>
<p>Portuguese_Portugal.1252</p>
<p>Para a base espanhola queria</p>
<p>spanish_Spain.1252</p>
<p><strong>Acrescentar definição no Windows Server 2008</strong></p>
<p>Trabalhamos aqui geralmente com duas instâncias de base de dados, uma local e uma remota, centralizada. Procurei resolver primeiro o caso no server, para verificar se era mesmo este o problema. Não tinha o pack espanhol instalado, e portanto puxei-o do site da Microsoft:</p>
<p><a href="http://www.microsoft.com/Downloads/details.aspx?familyid=03831393-EEF7-48A5-A69F-0CE72B883DF2&#038;displaylang=en">http://www.microsoft.com/Downloads/details.aspx?familyid=03831393-EEF7-48A5-A69F-0CE72B883DF2&#038;displaylang=en</a></p>
<p>ou para o Server 2008 c/ SP2</p>
<p><a href="http://www.microsoft.com/Downloads/details.aspx?familyid=3A7FB7A2-3519-495B-9BC5-2007082CA9A6&#038;displaylang=en">http://www.microsoft.com/Downloads/details.aspx?familyid=3A7FB7A2-3519-495B-9BC5-2007082CA9A6&#038;displaylang=en</a></p>
<p>ou para Server 2008 R2</p>
<p><a href="http://www.microsoft.com/Downloads/details.aspx?familyid=03831393-EEF7-48A5-A69F-0CE72B883DF2&#038;displaylang=en">http://www.microsoft.com/Downloads/details.aspx?familyid=03831393-EEF7-48A5-A69F-0CE72B883DF2&#038;displaylang=en</a></p>
<p>são ficheiros .img pelo que devem ser carregados numa drive virtual como o Virtual Clone Drive.</p>
<p>Depois em Control Panel > Regional and Language Options > Keyboards and Languages > Display Language aparece a lista de linguagens disponíveis e em uso pelo Windows. Há tb um botão &#8220;Install/uninstall Languages&#8221; que permite acrescentar. Deve no Wizard que aparece escolher a pasta da drive para a linguagem especifica e deixar correr a instalação. </p>
<p>No caso do espanhol, puxei o ficheiro do grupo 1, e no wizard escolhi a pasta &#8220;es-ES&#8221;. &#8220;Et voilá&#8221;, spanish_Spain.1252 fica disponível no PostgreSQL. Simples e resolvido.</p>
<p>O processo para as versões do 7 Ultimate e Business devem ser semelhantes. O problema surge para o Home. Não é suportado, mas é possível introduzir as definições de localização. Para tal guiei-me pelas notas em <a href="http://xaueious.wordpress.com/2009/08/22/changing-installed-language-of-windows-7-home-premium-pro-from-en-us/">http://xaueious.wordpress.com/2009/08/22/changing-installed-language-of-windows-7-home-premium-pro-from-en-us/</a> e segui o caminho da linha de comandos.</p>
<p><strong>Acrescentar definição no Windows 7 Home Premium</strong></p>
<ol>
<li>Descarregue o MUI associado à língua específica daqui <a href="http://www.froggie.sk/7lp64rtm.html">http://www.froggie.sk/7lp64rtm.html</a></li>
<li>Agora um dos truques: Se executares o ficheiro descarregado, é extraído um ficheiro &#8220;lp.cab&#8221; para a mesma pasta e que é fundamental preservar. No entanto, pouco depois de executar, o ficheiro desaparece. Portanto considera-o um pouco como um jogo de reacção, e prepara o ambiente para mover o ficheiro para outro local ou renomea-lo ASAP. Copy-paste não resulta.
        </li>
<li>Na linha de comandos, executado com privilégios de administrador, executa o seguinte comando:
<pre>DISM /Online /Add-Package /PackagePath:D:\Caminho\lp.cab</pre>
<p>onde D:\Caminho\lp.cab é o caminho completo para o ficheiro extraído.</li>
<p>O processo demora uns minutos, mas uma vez findado, no Postgre, é possível criar a base com as chaves de locale correctas e desejadas.</p>
]]></content:encoded>
			<wfw:commentRss>http://miguelalho.com/?feed=rss2&amp;p=1097</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mover Ficheiros De Um Repositório Para Outro com Subversion.</title>
		<link>http://miguelalho.com/?p=1085</link>
		<comments>http://miguelalho.com/?p=1085#comments</comments>
		<pubDate>Wed, 30 Jun 2010 13:56:11 +0000</pubDate>
		<dc:creator>Miguel Alho</dc:creator>
				<category><![CDATA[Programação]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[svnadmin dump]]></category>
		<category><![CDATA[svnadmin load]]></category>

		<guid isPermaLink="false">http://miguelalho.com/?p=1085</guid>
		<description><![CDATA[Ontem, num curta sessão de manutenção dos meus repositórios de Subversion, senti necessidade de reorganizar algumas, como creio ser &#8220;normal&#8221; ao fim de algum tempo. Tendo a organizar o meu SVN como múltiplos repositórios, um por projecto. Dentro de cada repositório tenho os diversos projectos de classes, sites ou aplicações associados. Tenho assim vários repositórios [...]]]></description>
			<content:encoded><![CDATA[<p>Ontem, num curta sessão de manutenção dos meus repositórios de Subversion, senti necessidade de reorganizar algumas, como creio ser &#8220;normal&#8221; ao fim de algum tempo. Tendo a organizar o meu SVN como múltiplos repositórios, um por projecto. Dentro de cada repositório tenho os diversos projectos de classes, sites ou aplicações associados. Tenho assim vários repositórios contextualizados e mais pequenos, em vez de um repositório geral com diversos projectos. A única dificuldade que apresenta é o backup / dump que obriga a manter um script com a lista de comandos de &#8220;<em>svnadmin dump</em>&#8221; para cada repositorio individual.</p>
<p>Também, apenas agora começo a usar a estrutura de pastas típicas do SVN &#8211; /trunk, /brenches e /tags, porque só agora tive necessidade de usar tags para marcar algumas situações. Mover as pastas dentre do repositório para incluir esta alteração é bastante simples, e com o ToirtoiseSVN no server, é drag n&#8217; drop. </p>
<p>Durante a reorganização, senti necessidade de mover alguns repositórios &#8211; essencialmente de projectos de testes &#8211; e uni-los num só repositório contextualizado. Mover pastas <em>dentro</em> de um repositório é muito simples, usando o commando <em>svn move</em> ou usando o RepoBrowser do ToirtoiseSVN Repo Browser. Mas entre repositórios é um pouco mais elaborado. é preciso efectuar o <em>dump </em>do repositórios, e recarrega-lo no novo repositório, preferencialmente indicando a nova pasta para a qual deve ser carregada. A vantagem é que o histórico de alterações é conservada (sofre apenas uma renumeração).</p>
<p>Para fazer o dump, o comando é:</p>

<div class="wp_syntax"><div class="code"><pre class="svn" style="font-family:monospace;">svnadmin dump d:\repoPathToMove &gt; d:\backupFolder\repoName.dump</pre></div></div>

<p>Para carregar o <em>dump </em>criado:</p>

<div class="wp_syntax"><div class="code"><pre class="svn" style="font-family:monospace;">svnadmin load d:\pathToNewRepo --parent-dir InternalFolder &lt; d:\backupFolder\repoName.dump</pre></div></div>

<p>De notar a opção <em>&#8211;parent-dir</em> onde indico a pasta do repositório para onde os ficheiros devem ser carregados. É necessário criar a pasta no repositório de destino antes de efectuar o <em>load</em>. Caso contrário é levantado um erro e os <em>dump </em>não é carregado. Uma forma mais simpels de o escrever (e sem criar o ficheiro <em>dump</em>) é:</p>

<div class="wp_syntax"><div class="code"><pre class="svn" style="font-family:monospace;">svnadmin dump d:\repoPathToMove | svnadmin load d:\pathToNewRepo --parent-dir InternalFolde</pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://miguelalho.com/?feed=rss2&amp;p=1085</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Less.js &#8211; Less em javascript!</title>
		<link>http://miguelalho.com/?p=1082</link>
		<comments>http://miguelalho.com/?p=1082#comments</comments>
		<pubDate>Sun, 20 Jun 2010 15:21:39 +0000</pubDate>
		<dc:creator>Miguel Alho</dc:creator>
				<category><![CDATA[Programação]]></category>
		<category><![CDATA[.Less]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Sass]]></category>

		<guid isPermaLink="false">http://miguelalho.com/?p=1082</guid>
		<description><![CDATA[O Less é um framework de escrita de css que permite utilizar variáveis, herança e outros coisas giras. Mencionei-o há uns posts atrás, linkando as versões de ruby e .net. As versões que mencionei são construídos server-side. Actualemnte, o Less está a ser portado para javascript, permitindo a mesma funcioanlidade mas processado do lado do [...]]]></description>
			<content:encoded><![CDATA[<p>O Less é um framework de escrita de css que permite utilizar variáveis, herança e outros coisas giras. Mencionei-o há uns <a href="http://miguelalho.com/?p=1066" target="_blank">posts atrás</a>, linkando as versões de ruby e .net. As versões que mencionei são construídos server-side. Actualemnte, o Less está a ser portado para javascript, permitindo a mesma funcioanlidade mas processado do lado do cliente. Este post refere essa evolução:</p>
<p><a href="http://fadeyev.net/2010/06/19/lessjs-will-obsolete-css/" target="_blank">http://fadeyev.net/2010/06/19/lessjs-will-obsolete-css/ </a></p>
<p>Outro framework do género a ver: Sass<a href="http://sass-lang.com/" target="_blank"> http://sass-lang.com/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://miguelalho.com/?feed=rss2&amp;p=1082</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Livros para trocas</title>
		<link>http://miguelalho.com/?p=1073</link>
		<comments>http://miguelalho.com/?p=1073#comments</comments>
		<pubDate>Sun, 06 Jun 2010 00:09:07 +0000</pubDate>
		<dc:creator>Miguel Alho</dc:creator>
				<category><![CDATA[Informática]]></category>
		<category><![CDATA[livros]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[troca]]></category>

		<guid isPermaLink="false">http://miguelalho.com/?p=1073</guid>
		<description><![CDATA[Tenho por aqui alguns livros que ou já li, ou que ainda não li mas também já não tenho grande interesse em manter por não ter perspectivas de ler. Na verdade, tenho acumulado alguns livros nas prateleiras que num momento ou noutro tinham interesse, mas neste momento não estou focados neles. Alguns nem comecei a [...]]]></description>
			<content:encoded><![CDATA[<p>Tenho por aqui alguns livros que ou já li, ou que ainda não li mas também já não tenho grande interesse em manter por não ter perspectivas de ler. Na verdade, tenho acumulado alguns livros nas prateleiras que num momento ou noutro tinham interesse, mas neste momento não estou focados neles. Alguns nem comecei a ler (infelizmente). Uma questão de prioridades&#8230;</p>
<p>O que procuro é orientar outros livros que me possam interessar, seja para referencia, seja para explorar novos temas. Não estou muito preocupado com o estado impecável dos livros, se bem que quanto melhor, melhor. Procuro mais livros sobre algoritmia, padrões de código, e arquitectura, como também algumas tecnologias / linguagens como o Ruby, Processing, OpenFrameworks, ASP.NET MVC, Javascript, AJAX, Programação por objectos, Mecurial, Git, temas avançados de Web Services / WCF / SOA e C# e Asp.NET, DSLs, NHibernate, Code Generation, Silverlight, WPF, aspectos de engenharia de software, desenvolvimento de aplicações (processo e gestão) e até o &#8220;business side&#8221; das coisas&#8230; </p>
<p>Os que já não preciso:</p>
<li class="bullet"><a href="http://apress.com/book/view/9781430210191" target="_blank">Expert C# 2008 Business Objects</a>
<p class="inner">Este livro é acerca da framework  CLSA.NET &#8211; uma framework muito completa para desenvolvimento de aplicações, escrito pelo autor do projecto. Comprei na altura para puxar algumas ideias para a minha própria framework.Tirei algumas ideias que me interessavam na altura.</p>
</li>
<li class="bullet"><a href="http://pragprog.com/titles/kpiod/interface-oriented-design" target="_blank">Interface-Oriented Design</a>
<p class="inner">Sou fã dos livros da Pragmatic Bookshelf. Tenho alguns lidos e por ler, quer físicos quer ebooks. Este é interessante e discute abordagens de design de código recorrendo a interfaces.</p>
</li>
<li class="bullet"><a href="http://www.amazon.com/Object-Oriented-Thought-Process-3rd/dp/0672330164/ref=dp_ob_title_bk" target="_blank">The Object Oriented Thought Process</a>
<p class="inner"> Este foi lido com alguma rapidez e está interessante. Comprei este livro com o intuíto de ajudar aqui o pessoal a readquirir alguns dos conceitos de programação por objectos. A descrição podia ser melhor, especialmente nas questões básicas, Ainda assim, aborda com exemplos e algumas figuras a POO.</p>
</li>
<li class="bullet"><a href="http://www.amazon.com/Visual-Studio-Tools-Office-InfoPath/dp/0321334884" target="_blank">Visual Studio Tools for Office </a>
<p class="inner"> Num projecto, estava planeado desenvolver uns componentes para integrar com o Outlook, e na altura.. siga livros para estudar. Felizmente não foi necessário. De qualquer forma, neste caso, tinha acertado na versão errada do livro &#8211; Office 2003 &#8211; e portanto pode não servir para todos. De qualquer forma pode ser útil para alguém em termos e sistemas legados?</p>
</li>
<li class="bullet"><a href="http://www.amazon.com/Professional-Outlook-2007-Programming-Programmer/dp/0470049944/ref=sr_1_2?ie=UTF8&#038;s=books&#038;qid=1275782112&#038;sr=1-2" target="_blank">Outlook 2007 Programming</a>
<p class="inner">idêntico ao anterior em termos de objectivo, mas este livro estava orientado À versão correcta. Tal como o anterior, estão novíssimos.</p>
</li>
<li class="bullet"><a href="http://www.amazon.com/IronPython-Action-Michael-J-Foord/dp/1933988339/ref=sr_1_1?ie=UTF8&#038;s=books&#038;qid=1275782355&#038;sr=1-1" target="_blank">Iron Python In Action</a>
<p class="inner"> Este comprei no sentido de aprender uma nova linguagem. Preferencialmente uma dinâmica, para captar novos modos e abordagens a resolução de problemas e algoritmos, e o Python parecia-me bom candidato. Tinha na altura visto vídeos acerca do Iron Python em Silverlight e isso despertou-me. Infelizmente as prioridades impediram-me de ver este livro. Hoje preferia Iron Ruby, já que temos alguns projectos com o Ruby (normal) a decorrer. Mais um novíssimo&#8230;</p>
</li>
<li class="bullet"><a href="http://www.amazon.com/SQL-Server-2008-Administration-Action/dp/193398872X/ref=sr_1_3?ie=UTF8&#038;s=books&#038;qid=1275782557&#038;sr=1-3" target="_blank">SQL Server 2008 Administration in Action</a>
<p class="inner">Mais uma associado a um caminho provável de um projecto que teria de estudar. Ja tinha conhecimentos com o 2005, mas ainda não conhecia as novidades do 2008, muito menos as ferramentas de gestão das mesmas. Está novíssimo, pois não foi necessário ver, e as prioridades, como sempre, fizeram-me escolher outros primeiro.</p>
</li>
<p>Quem tiver interesse num destes títulos, digam qualquer coisa. Ou se tiverem títulos interessantes, listam-nos cá nos comentários! <img src='http://miguelalho.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://miguelalho.com/?feed=rss2&amp;p=1073</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby Warrior</title>
		<link>http://miguelalho.com/?p=1070</link>
		<comments>http://miguelalho.com/?p=1070#comments</comments>
		<pubDate>Fri, 04 Jun 2010 00:23:04 +0000</pubDate>
		<dc:creator>Miguel Alho</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[IA]]></category>
		<category><![CDATA[inteligência artificial]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby Warrior]]></category>

		<guid isPermaLink="false">http://miguelalho.com/?p=1070</guid>
		<description><![CDATA[Acabei há instantes o nível intermédio (o segundo dos dois níveis) do Ruby-Warrior, um jogo criado para ensinar inteligência artificial com base em Ruby. O jogo é muito simples e muito divertido, especialmente para quem é geek (lol) e gosta de programar. Aqui no escritório temos o desafio interno de terminar o jogo sem recorrer [...]]]></description>
			<content:encoded><![CDATA[<p>Acabei há instantes o nível intermédio (o segundo dos dois níveis) do <a href="http://github.com/ryanb/ruby-warrior" target="_blank">Ruby-Warrior</a>, um jogo criado para ensinar inteligência artificial com base em Ruby. O jogo é muito simples e muito divertido, especialmente para quem é <em>geek </em>(lol) e gosta de programar. Aqui no escritório temos o desafio interno de terminar o jogo sem recorrer a ajudas externas. Felizmente consegui sem externas e quase sem usar as pistas que o jogo nos dá quando morremos.</p>
<p>O jogo é muito simples &#8211; visualmente é texto na linha de comandos &#8211; e temos de mover a nossa personagem pelos diversos níveis da torre, para chegar ao topo e salvar a princesa. Pelo meio vamos encontrando diversos inimigos e pessoal que precisa de ser salvo. No jogo, programamos a nossa personagem de modo a tomar as decisões correctas para ultrapassar os inimigos e chegar à escadaria de cada nível.</p>
<p>O modo iniciante é jogado apenas a uma dimensão (um eixo apenas) enquanto o segundo modo (intermédio) já decorre a duas dimensões tornando necessário implementar decisões de prioridade relativo a direcções em que devemos actuar. Assim, somos obrigados a analisar o meio envolvente e prioritizar as acções. </p>
<p>O jogo é muito giro, e permite ensinar bastante acerca do Ruby, especialmente a definição de métodos e mecanismos de controlo (if /elsif /else e array e for). Também ajuda a descubrir formas de criar decisões em código.</p>
<p>Recomendo vivamente experimentarem &#8211; o código pode ser puxado <a href="http://github.com/ryanb/ruby-warrior" target="_blank">do GitHub do Ryan Bate</a>. Tinha pensado colocar aqui o meu código, mas achei melhor não.. é melhor experimentar e descobrir. Se bem que posso partilhar a minha solução com quem quiser ver <img src='http://miguelalho.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://miguelalho.com/?feed=rss2&amp;p=1070</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>.Less (Dot Less) -&gt; &#8220;CSS on Steroids&#8221;</title>
		<link>http://miguelalho.com/?p=1066</link>
		<comments>http://miguelalho.com/?p=1066#comments</comments>
		<pubDate>Thu, 03 Jun 2010 18:46:41 +0000</pubDate>
		<dc:creator>Miguel Alho</dc:creator>
				<category><![CDATA[ASP.NET]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[.Less]]></category>
		<category><![CDATA[.net]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[T4]]></category>

		<guid isPermaLink="false">http://miguelalho.com/?p=1066</guid>
		<description><![CDATA[Ainda no outro dia, falava com os meus colegas de como seria muito bom que o CSS tivesse estruturas de herança incorporados e variáveis.. especialmente variáveis, para não ter de definir constantemente as mesmas coisas.
E hoje enquanto lia o blog do Spaanjaars, descubir o .Less, uma biblioteca dedicada a extender o CSS, introduzindo variáveis e [...]]]></description>
			<content:encoded><![CDATA[<p>Ainda no outro dia, falava com os meus colegas de como seria muito bom que o CSS tivesse estruturas de herança incorporados e variáveis.. especialmente variáveis, para não ter de definir constantemente as mesmas coisas.</p>
<p>E hoje enquanto lia o <a href="http://imar.spaanjaars.com/536/using-less-to-change-the-way-you-write-your-css" target="_blank">blog do Spaanjaars</a>, descubir o <a href="http://dotlesscss.com/" target="_blank">.Less</a>, uma biblioteca dedicada a extender o CSS, introduzindo variáveis e esquemas de herança.  Soa bem? Se soa!! <img src='http://miguelalho.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p>Com o .Less, podemos escrever codigo com variáveis:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"><span style="color: #a1a100;">@brand_color: #4D926F;</span>
&nbsp;
<span style="color: #cc00cc;">#header</span> <span style="color: #00AA00;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">color</span><span style="color: #00AA00;">:</span> <span style="color: #a1a100;">@brand_color;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
h2 <span style="color: #00AA00;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">color</span><span style="color: #00AA00;">:</span> <span style="color: #a1a100;">@brand_color;</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>

<p>Ou nestings de selectores:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"><span style="color: #cc00cc;">#header</span> <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">color</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">red</span><span style="color: #00AA00;">;</span>
    a <span style="color: #00AA00;">&#123;</span>
       <span style="color: #000000; font-weight: bold;">font-weight</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">bold</span><span style="color: #00AA00;">;</span>
       <span style="color: #000000; font-weight: bold;">text-decoration</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">none</span><span style="color: #00AA00;">;</span>
    <span style="color: #00AA00;">&#125;</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>

<p>Ou misturas de elementos:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;">.rounded_corners<span style="color: #00AA00;">&#40;</span><span style="color: #a1a100;">@radius: 5px) {</span>
  -moz-border-radius<span style="color: #00AA00;">:</span> <span style="color: #a1a100;">@radius;</span>
  -webkit-border-radius<span style="color: #00AA00;">:</span> <span style="color: #a1a100;">@radius;</span>
  border-radius<span style="color: #00AA00;">:</span> <span style="color: #a1a100;">@radius;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #cc00cc;">#header</span> <span style="color: #00AA00;">&#123;</span>
  .rounded_corners<span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #cc00cc;">#footer</span> <span style="color: #00AA00;">&#123;</span>
  .rounded_corners<span style="color: #00AA00;">&#40;</span><span style="color: #933;">10px</span><span style="color: #00AA00;">&#41;</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>

<p>Lindo, né? Originalmente, o <a href="http://lesscss.org/" target="_blank">Less foi construído para o Ruby</a> (é um gem para o Ruby), mas um grupo converteu-o para .Net, criando o .Less. E ainda bem! No .Net, funciona como um HTTPHandler. Os ficheiros de CSS são ficheiros .less que são transformados aquando do pedido da página. É também possível <a href="http://haacked.com/archive/2009/12/02/t4-template-for-less-css.aspx" target="_blank">usar templates T4</a> para criar versões estáticas do CSS.</p>
<p>A experimentar!</p>
]]></content:encoded>
			<wfw:commentRss>http://miguelalho.com/?feed=rss2&amp;p=1066</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TEDxAveiro.. a Poucas Horas! :D</title>
		<link>http://miguelalho.com/?p=1064</link>
		<comments>http://miguelalho.com/?p=1064#comments</comments>
		<pubDate>Sat, 29 May 2010 00:07:34 +0000</pubDate>
		<dc:creator>Miguel Alho</dc:creator>
				<category><![CDATA[Extra]]></category>
		<category><![CDATA[Migos]]></category>
		<category><![CDATA[portal]]></category>
		<category><![CDATA[TED]]></category>
		<category><![CDATA[TEDxAveiro]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://miguelalho.com/?p=1064</guid>
		<description><![CDATA[Por aqui, é uma da manhã e ainda andamos a ultimar alguns detalhes para a apresentação que o meu colega Victor Martins irá fazer do Migos.org, uma plataforma com objectivos de potenciar a acção voluntária. A plataforma tem sido desenvolvido, nos últimos dois meses, aqui no escritório, com a participação da nossa equipa e ainda [...]]]></description>
			<content:encoded><![CDATA[<p>Por aqui, é uma da manhã e ainda andamos a ultimar alguns detalhes para a apresentação que o meu colega Victor Martins irá fazer do <a href="http://www.migos.org">Migos.org</a>, uma plataforma com objectivos de potenciar a acção voluntária. A plataforma tem sido desenvolvido, nos últimos dois meses, aqui no escritório, com a participação da nossa equipa e ainda alguns estagiários nossos. A apresentação será o segundo tema do primeiro bloco, que irá começar às 9:30. </p>
<p>O melhor de tudo é que, para quem não poder estar presente, será possível ver em directo e online! o link:</p>
<p><a href="http://tedxaveiro.com/">http://tedxaveiro.com/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://miguelalho.com/?feed=rss2&amp;p=1064</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
