<?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>The GITS Blog</title>
	<atom:link href="http://ginstrom.com/scribbles/feed/" rel="self" type="application/rss+xml" />
	<link>http://ginstrom.com/scribbles</link>
	<description>Random scribbling about programming, translation, and Japan</description>
	<lastBuildDate>Fri, 11 May 2012 05:10:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Continuous integration in python using watchdog</title>
		<link>http://ginstrom.com/scribbles/2012/05/10/continuous-integration-in-python-using-watchdog/</link>
		<comments>http://ginstrom.com/scribbles/2012/05/10/continuous-integration-in-python-using-watchdog/#comments</comments>
		<pubDate>Thu, 10 May 2012 06:00:53 +0000</pubDate>
		<dc:creator>Ryan Ginstrom</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://ginstrom.com/scribbles/?p=1752</guid>
		<description><![CDATA[watchdog is a cross-platform python module for watching directories for changes. I use watchdog to run continuous integration on my projects: every time a file changes (e.g. is saved, deleted, or created) in the directory I am watching, a script will automatically run unit tests, compile libraries, build docs, and run other tests, as necessary. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://packages.python.org/watchdog/" title="watchdog package">watchdog</a> is a cross-platform python module for watching directories for changes.</p>
<p>I use watchdog to run continuous integration on my projects: every time a file changes (e.g. is saved, deleted, or created) in the directory I am watching, a script will automatically run unit tests, compile libraries, build docs, and run other tests, as necessary.</p>
<p>Below is a sample script using watchdog that monitors the current directory for changes to .py files and .rst files. When a .py file changes, it runs unit tests; when a .rst file changes, it builds the documentation. Here, I assume that the documentation is built using <a href="http://sphinx.pocoo.org/" title="Sphinx documentation tool overview">Sphinx</a>, and is located in the `docs` subdirectory. `python -m unittest discover -b` is used to run the unit tests.</p>
<p>Of course, you could perform any actions you wanted, using any triggers you choose.</p>
<p>The first thing that you need to do is define an event handler based on <code>watchdog.FileSystemEventHandler</code>:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">import</span> <span class="kw3">os</span><br />
<span class="kw1">from</span> watchdog.<span class="me1">events</span> <span class="kw1">import</span> FileSystemEventHandler</p>
<p>
<span class="kw1">def</span> getext<span class="br0">&#40;</span>filename<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;Get the file extension.&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">splitext</span><span class="br0">&#40;</span>filename<span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">-1</span><span class="br0">&#93;</span>.<span class="me1">lower</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">class</span> ChangeHandler<span class="br0">&#40;</span>FileSystemEventHandler<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
&nbsp; &nbsp; React to changes in Python and Rest files by<br />
&nbsp; &nbsp; running unit tests (Python) or building docs (.rst)<br />
&nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> on_any_event<span class="br0">&#40;</span><span class="kw2">self</span>, event<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;If any file or folder is changed&quot;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> event.<span class="me1">is_directory</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> getext<span class="br0">&#40;</span>event.<span class="me1">src_path</span><span class="br0">&#41;</span> == <span class="st0">'.py'</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; run_tests<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">elif</span> getext<span class="br0">&#40;</span>event.<span class="me1">src_path</span><span class="br0">&#41;</span> == <span class="st0">'.rst'</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; build_docs<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>Here, I'm catching all file events, and reacting to changes to .py and .rst (reStructured text) files.</p>
<p>The next thing is to create a <code>watchdog.Observer</code>, and register your event handler.</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">import</span> <span class="kw3">os</span><br />
<span class="kw1">import</span> <span class="kw3">time</span></p>
<p><span class="kw1">from</span> watchdog.<span class="me1">observers</span> <span class="kw1">import</span> Observer</p>
<p>BASEDIR = <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">abspath</span><span class="br0">&#40;</span><span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">dirname</span><span class="br0">&#40;</span>__file__<span class="br0">&#41;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> main<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
&nbsp; &nbsp; Called when run as main.<br />
&nbsp; &nbsp; Look for changes to code and doc files.<br />
&nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">while</span> <span class="nu0">1</span>:<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; event_handler = ChangeHandler<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; observer = Observer<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; observer.<span class="me1">schedule</span><span class="br0">&#40;</span>event_handler, BASEDIR, recursive=<span class="kw2">True</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; observer.<span class="me1">start</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">while</span> <span class="kw2">True</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">time</span>.<span class="me1">sleep</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">except</span> <span class="kw2">KeyboardInterrupt</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; observer.<span class="me1">stop</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; observer.<span class="me1">join</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">if</span> __name__ == <span class="st0">'__main__'</span>:<br />
&nbsp; &nbsp; main<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>Finally, define your actions. Here are mine for running unit tests and building my docs.</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">import</span> <span class="kw3">os</span><br />
<span class="kw1">import</span> <span class="kw3">sys</span><br />
<span class="kw1">import</span> <span class="kw3">subprocess</span><br />
<span class="kw1">import</span> <span class="kw3">datetime</span><br />
<span class="kw1">import</span> <span class="kw3">time</span></p>
<p>BASEDIR = <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">abspath</span><span class="br0">&#40;</span><span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">dirname</span><span class="br0">&#40;</span>__file__<span class="br0">&#41;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> get_now<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;Get the current date and time as a string&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw3">datetime</span>.<span class="kw3">datetime</span>.<span class="me1">now</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">strftime</span><span class="br0">&#40;</span><span class="st0">&quot;%Y/%m/%d %H:%M:%S&quot;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> build_docs<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
&nbsp; &nbsp; Run the Sphinx build (`make html`) to make sure we have the<br />
&nbsp; &nbsp; latest version of the docs<br />
&nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">print</span> &gt;&gt; <span class="kw3">sys</span>.<span class="me1">stderr</span>, <span class="st0">&quot;Building docs at %s&quot;</span> % get_now<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw3">os</span>.<span class="me1">chdir</span><span class="br0">&#40;</span><span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">join</span><span class="br0">&#40;</span>BASEDIR, <span class="st0">&quot;docs&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw3">subprocess</span>.<span class="me1">call</span><span class="br0">&#40;</span>r<span class="st0">'make.bat html'</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> run_tests<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;Run unit tests with unittest.&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">print</span> &gt;&gt; <span class="kw3">sys</span>.<span class="me1">stderr</span>, <span class="st0">&quot;Running unit tests at %s&quot;</span> % get_now<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw3">os</span>.<span class="me1">chdir</span><span class="br0">&#40;</span>BASEDIR<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw3">subprocess</span>.<span class="me1">call</span><span class="br0">&#40;</span>r<span class="st0">'python -m unittest discover -b'</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>Here is the full code listing:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
Monitors our code &amp; docs for changes<br />
&quot;</span><span class="st0">&quot;&quot;</span></p>
<p><span class="kw1">import</span> <span class="kw3">os</span><br />
<span class="kw1">import</span> <span class="kw3">sys</span><br />
<span class="kw1">import</span> <span class="kw3">subprocess</span><br />
<span class="kw1">import</span> <span class="kw3">datetime</span><br />
<span class="kw1">import</span> <span class="kw3">time</span></p>
<p><span class="kw1">from</span> watchdog.<span class="me1">observers</span> <span class="kw1">import</span> Observer<br />
<span class="kw1">from</span> watchdog.<span class="me1">events</span> <span class="kw1">import</span> FileSystemEventHandler</p>
<p>
BASEDIR = <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">abspath</span><span class="br0">&#40;</span><span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">dirname</span><span class="br0">&#40;</span>__file__<span class="br0">&#41;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> get_now<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;Get the current date and time as a string&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw3">datetime</span>.<span class="kw3">datetime</span>.<span class="me1">now</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">strftime</span><span class="br0">&#40;</span><span class="st0">&quot;%Y/%m/%d %H:%M:%S&quot;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> build_docs<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
&nbsp; &nbsp; Run the Sphinx build (`make html`) to make sure we have the<br />
&nbsp; &nbsp; latest version of the docs<br />
&nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">print</span> &gt;&gt; <span class="kw3">sys</span>.<span class="me1">stderr</span>, <span class="st0">&quot;Building docs at %s&quot;</span> % get_now<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw3">os</span>.<span class="me1">chdir</span><span class="br0">&#40;</span><span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">join</span><span class="br0">&#40;</span>BASEDIR, <span class="st0">&quot;docs&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw3">subprocess</span>.<span class="me1">call</span><span class="br0">&#40;</span>r<span class="st0">'make.bat html'</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> run_tests<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;Run unit tests with unittest.&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">print</span> &gt;&gt; <span class="kw3">sys</span>.<span class="me1">stderr</span>, <span class="st0">&quot;Running unit tests at %s&quot;</span> % get_now<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw3">os</span>.<span class="me1">chdir</span><span class="br0">&#40;</span>BASEDIR<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw3">subprocess</span>.<span class="me1">call</span><span class="br0">&#40;</span>r<span class="st0">'python -m unittest discover -b'</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> getext<span class="br0">&#40;</span>filename<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;Get the file extension.&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">splitext</span><span class="br0">&#40;</span>filename<span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">-1</span><span class="br0">&#93;</span>.<span class="me1">lower</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">class</span> ChangeHandler<span class="br0">&#40;</span>FileSystemEventHandler<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
&nbsp; &nbsp; React to changes in Python and Rest files by<br />
&nbsp; &nbsp; running unit tests (Python) or building docs (.rst)<br />
&nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> on_any_event<span class="br0">&#40;</span><span class="kw2">self</span>, event<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;If any file or folder is changed&quot;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> event.<span class="me1">is_directory</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> getext<span class="br0">&#40;</span>event.<span class="me1">src_path</span><span class="br0">&#41;</span> == <span class="st0">'.py'</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; run_tests<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">elif</span> getext<span class="br0">&#40;</span>event.<span class="me1">src_path</span><span class="br0">&#41;</span> == <span class="st0">'.rst'</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; build_docs<span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> main<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
&nbsp; &nbsp; Called when run as main.<br />
&nbsp; &nbsp; Look for changes to code and doc files.<br />
&nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">while</span> <span class="nu0">1</span>:<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; event_handler = ChangeHandler<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; observer = Observer<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; observer.<span class="me1">schedule</span><span class="br0">&#40;</span>event_handler, BASEDIR, recursive=<span class="kw2">True</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; observer.<span class="me1">start</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">while</span> <span class="kw2">True</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">time</span>.<span class="me1">sleep</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">except</span> <span class="kw2">KeyboardInterrupt</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; observer.<span class="me1">stop</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; observer.<span class="me1">join</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">if</span> __name__ == <span class="st0">'__main__'</span>:<br />
&nbsp; &nbsp; main<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>You can <a href="/code/monitor_changes.zip" title="monitor_changes.py script (zipped)">download the code here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://ginstrom.com/scribbles/2012/05/10/continuous-integration-in-python-using-watchdog/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The importance of appearing confident</title>
		<link>http://ginstrom.com/scribbles/2012/04/16/the-importance-of-appearing-confident/</link>
		<comments>http://ginstrom.com/scribbles/2012/04/16/the-importance-of-appearing-confident/#comments</comments>
		<pubDate>Mon, 16 Apr 2012 08:09:01 +0000</pubDate>
		<dc:creator>Ryan Ginstrom</dc:creator>
				<category><![CDATA[freelancing]]></category>
		<category><![CDATA[translation]]></category>

		<guid isPermaLink="false">http://ginstrom.com/scribbles/?p=1746</guid>
		<description><![CDATA[I've been neglecting this blog for some time, but thanks to a nice reminder from a reader, I'm back. As translators, we need to be humble about our work. Translation spans so many fields, from foreign-language study, to writing, to subject-matter knowledge&#8211;not to mention the actual skill of translation&#8211;that it's nearly impossible to fully master [...]]]></description>
			<content:encoded><![CDATA[<p>I've been neglecting this blog for some time, but thanks to a nice reminder from a reader, I'm back. <img src='http://ginstrom.com/scribbles/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>As translators, we need to be humble about our work. Translation spans so many fields, from foreign-language study, to writing, to subject-matter knowledge&#8211;not to mention the actual skill of translation&#8211;that it's nearly impossible to fully master every aspect of our profession.</p>
<p>Part of this humility means being willing to consider that you might be wrong. Even if I'm confident about a translation, I think seriously about any feedback I get. In fact, a lot of my mistakes come from translations I'm very confident about, because I'm less likely to do a lot of deep thinking over "simple" translations.</p>
<p>That said, translators also need to give their clients an appearance of confidence. If you don't seem confident about your translation, your client will be even less confident about it. </p>
<p>I experienced this early in my career, with one of my first clients. When this client asked whether an alternative translation would work, I'd accept their alternative whenever possible. If the client claimed that one of my translations was incorrect, I'd fix it to their liking.</p>
<p>Of course, being a new translator I made a lot more mistakes than I do now. And I was eager to please, because I didn't have a lot of clients.</p>
<p>But I was changing my translations even when my original was actually better (and their change was plain wrong). Over time, this client asked for more and more changes, to the point where they (native speakers of Japanese with dubious English-language ability) were "teaching" me the finer points of English grammar. Although this often provided some needed comic relief, it took time away from actual translation work, and hurt the quality of my translations.</p>
<p>I learned from that experience to stick to my guns with my translations. I consider my client's feedback, but if I still believe my translation to be the best, then I'll let the client know, and explain why. If the client still insists on the change, I'll make it&#8211;but letting the client know the problem.</p>
<p>It took a lot of work, and a lot of patient explaining, but over time my clients began to accept a response of "the original is better"; and they began asking fewer questions as well. Of course, I was also getting better over this time, but I'm certain that my greater show of confidence also helped.</p>
<p><strong>Don't offer alternative translations</strong></p>
<p>This is another way to appear to lack confidence. When you're not sure about how something should be translated, it can be tempting to offer a couple of alternatives for the client to choose from. You might even think that you're offering a greater service by doing this. I think that this is a mistake for a few reasons:</p>
<ol>
<li>It sends the message that you lack confidence.</li>
<li>It makes the client choose, and people hate to make choices (<a href="http://www.ted.com/talks/barry_schwartz_on_the_paradox_of_choice.html" title="TED talk on paradox of choice">they think they do, but are more satisfied when they don't have to make them</a>).</li>
<li>It assumes your client is better able to choose the right translation than you are (if so, why did they hire you?).</li>
<li>It probably means you didn't ask enough questions about the purpose of the document (Is it for a general audience, or for engineers? For in-house use, or publication?). The more you know about what the document is for, the more sure you'll be about how to translate it.</li>
</ol>
<p>Although it's important to be humble about your work, there's a fine line between humility and wishy-washiness. Just as important as accepting client feedback is projecting an attitude that says, "Trust me, I'm an expert."</p>
]]></content:encoded>
			<wfw:commentRss>http://ginstrom.com/scribbles/2012/04/16/the-importance-of-appearing-confident/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Life in America</title>
		<link>http://ginstrom.com/scribbles/2011/04/20/life-in-america/</link>
		<comments>http://ginstrom.com/scribbles/2011/04/20/life-in-america/#comments</comments>
		<pubDate>Wed, 20 Apr 2011 05:09:45 +0000</pubDate>
		<dc:creator>Ryan Ginstrom</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://ginstrom.com/scribbles/?p=1741</guid>
		<description><![CDATA[Note: although I am now a Nintendo employee, my postings should not in any way be interpreted as being on behalf of or condoned by Nintendo. They are my personal views only. And now that that's out of the way&#8230; It's been a whirlwind month. I left Okinawa on March 10, just one day before [...]]]></description>
			<content:encoded><![CDATA[<p><em>Note: although I am now a Nintendo employee, my postings should not in any way be interpreted as being on behalf of or condoned by Nintendo. They are my personal views only. And now that that's out of the way&#8230;</em></p>
<p>It's been a whirlwind month. I left Okinawa on March 10, just one day before the Tohoku earthquake. By the time I had recovered from my jetlag, I saw on the news that the earthquake had hit, but I was unable to get through and check on my family for a nerve-wracking day. (My family is staying in Okinawa for a few months so that my son can finish the school year, and my wife can work on the move from that side.)</p>
<p>When I first got back to the US, I experienced a bit of reverse culture shock, which is to be expected after living in Japan for nearly 12 years. Over that time, you forget some things, and other things change, so returning to my home country was like entering a slightly different dimension resembling home but not quite it. Having to find a house, buy a car, get a driver license (my US one having expired), etc. in the space of a month made it even more of a challenge.</p>
<p>But I'm pretty much used to being an American again, and although Seattle locals like to complain about the rain here, this really is a beautiful place. Mountains, rivers, lakes, forest, ocean &#8212; it's a nature-lover's paradise. Combine that with great coffee and beer, good music and art scenes, and friendly, cosmopolitan people, and I probably could have chosen a worse place to repatriate.</p>
<p>It sucks being away for my family for this long, but with modern wonders like skype and email, it's a little more bearable. The last time my wife and I were apart this long, it was before we were married, and we had to make do with letters and the occasional phone call (remember how expensive international calls were way back when?).</p>
<p>I definitely plan to keep on blogging, so now that this status report is out of the way, please stay tuned for more of my inane blather about programming, translation, and Japan.</p>
]]></content:encoded>
			<wfw:commentRss>http://ginstrom.com/scribbles/2011/04/20/life-in-america/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Version 2.1 of Count Anything released</title>
		<link>http://ginstrom.com/scribbles/2011/02/20/version-2-1-of-count-anything-released/</link>
		<comments>http://ginstrom.com/scribbles/2011/02/20/version-2-1-of-count-anything-released/#comments</comments>
		<pubDate>Sun, 20 Feb 2011 13:30:05 +0000</pubDate>
		<dc:creator>Ryan Ginstrom</dc:creator>
				<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://ginstrom.com/scribbles/?p=1738</guid>
		<description><![CDATA[I just released version 2.1 of my free word-counting program, Count Anything. Click here to get the latest version. This is a minor release with two fixes: the "No" button of the check for updates dialog was broken, and files on the results page are now in alphabetical order (in the next release, I'll make [...]]]></description>
			<content:encoded><![CDATA[<p>I just released version 2.1 of my free word-counting program, Count Anything.</p>
<p><a href="http://ginstrom.com/CountAnything/">Click here to get the latest version</a>.</p>
<p>This is a minor release with two fixes: the "No" button of the check for updates dialog was broken, and files on the results page are now in alphabetical order (in the next release, I'll make all the columns sortable by clicking).</p>
<p>Count Anything is free and released under the <a href="https://secure.wikimedia.org/wikipedia/en/wiki/MIT_License">MIT license</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://ginstrom.com/scribbles/2011/02/20/version-2-1-of-count-anything-released/feed/</wfw:commentRss>
		<slash:comments>35</slash:comments>
		</item>
		<item>
		<title>Going to work for the (short, Italian) Man</title>
		<link>http://ginstrom.com/scribbles/2011/02/14/going-to-work-for-the-short-italian-man/</link>
		<comments>http://ginstrom.com/scribbles/2011/02/14/going-to-work-for-the-short-italian-man/#comments</comments>
		<pubDate>Mon, 14 Feb 2011 04:16:44 +0000</pubDate>
		<dc:creator>Ryan Ginstrom</dc:creator>
				<category><![CDATA[translation]]></category>

		<guid isPermaLink="false">http://ginstrom.com/scribbles/?p=1735</guid>
		<description><![CDATA[Last week, I took a job as a technical translator at Nintendo of America. I'll be moving to Redmond, Washington at the end of February, and my family will move out there permanently in June. While it'll be hard to leave behind my life of relative freedom in sunny, laid-back Okinawa for the corporate world [...]]]></description>
			<content:encoded><![CDATA[<p>Last week, I took a job as a technical translator at <a href="http://www.nintendo.com/">Nintendo of America</a>. I'll be moving to Redmond, Washington at the end of February, and my family will move out there permanently in June.</p>
<p>While it'll be hard to leave behind my life of relative freedom in sunny, laid-back Okinawa for the corporate world in rainy Washington, I'm actually really excited about this move. Firstly, it's like this job was made for someone with my somewhat unusual combination of programming and translation skills. There will also be a lot of opportunities to learn, both from daily interaction with hardware and software engineers, to working alongside veteran translators. Among Nintendo's many benefits, they also have a tuition reimbursement program and encourage employees to take higher degrees.</p>
<p>One of the main problems I've faced working alone, without even many colleagues around to talk with in real life, is that I've found it hard to grow professionally. Sure, I can get better at what I'm already doing, but branching out and learning new things is a challenge. I turned 40 last year, and that got me thinking that I'm not done learning, so the offer from Nintendo came at just the right time. </p>
<p>It will also be good to live in the US for a while. My son is half American, but he's lived 12 of his nearly 13 years in Japan; it will be good for him to live in the US for a while, and it will prepare him for university there if that's what he decides to do. My wife is also ready to live in the US for a while, although of course there are many things we're going to miss about Japan (and especially Okinawa).</p>
<p>Coming right at the age of 40, it's struck me that maybe this is my own mid-life crisis &#8212; but at least taking a new job is a milder form of mid-life crisis than some of the men my age I know. Heck, I didn't even go buy a Harley. <img src='http://ginstrom.com/scribbles/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://ginstrom.com/scribbles/2011/02/14/going-to-work-for-the-short-italian-man/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>The Dunning–Kruger effect and you</title>
		<link>http://ginstrom.com/scribbles/2011/01/13/the-dunning%e2%80%93kruger-effect-and-you/</link>
		<comments>http://ginstrom.com/scribbles/2011/01/13/the-dunning%e2%80%93kruger-effect-and-you/#comments</comments>
		<pubDate>Wed, 12 Jan 2011 15:00:54 +0000</pubDate>
		<dc:creator>Ryan Ginstrom</dc:creator>
				<category><![CDATA[translation]]></category>

		<guid isPermaLink="false">http://ginstrom.com/scribbles/?p=1725</guid>
		<description><![CDATA[According to Wikipedia, The Dunning–Kruger effect is a cognitive bias in which unskilled people make poor decisions and reach erroneous conclusions, but their incompetence denies them the metacognitive ability to realize their mistakes. The more ignorant you are about a subject, the easier it seems to you. When I was starting out as a translator, [...]]]></description>
			<content:encoded><![CDATA[<p>According to <a href="https://secure.wikimedia.org/wikipedia/en/wiki/Dunning%E2%80%93Kruger_effect">Wikipedia</a>, </p>
<blockquote><p>The Dunning–Kruger effect is a cognitive bias in which unskilled people make poor decisions and reach erroneous conclusions, but their incompetence denies them the metacognitive ability to realize their mistakes.</p></blockquote>
<p>The more ignorant you are about a subject, the easier it seems to you. When I was starting out as a translator, I got bitten by this more times than I like to remember. </p>
<p>Paper and pulp? Why not &#8212; how hard could it be? I use paper every day, and once I took a paper-making class. A survey on healthcare in Vietnam? I just had my checkup last month, and I LOVE Vietnamese food. And so on.</p>
<p>Even when I glanced over a document ahead of time, it seemed easy &#8212; it wasn't until I actually dug into the translation (after accepting the job, of course <img src='http://ginstrom.com/scribbles/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' />  ) that I realized I was over my head.</p>
<p>As a corollary, the more we know about a subject, the more likely we are to know our limitations. For example, although I specialize in IT and telecoms, I refuse to do electronics or chip-making stuff. I <em>know</em> how hard that stuff is.</p>
<p>The problem with the Dunning–Kruger effect is that you actually believe that you can do a good job. How do you know to turn down a job when you think you can do it? </p>
<p>After a while, I developed a kind of sanity check when offered a job in a new field. I ask myself how long actual experts in the field study. Then I ask myself if I have studied that field long enough to duplicate their understanding. </p>
<p>And then for good measure, I think about all the botched translations I've seen in my fields by people who said, "Why not &#8212; I own a copy of Windows and play Minefield ALL THE TIME."</p>
]]></content:encoded>
			<wfw:commentRss>http://ginstrom.com/scribbles/2011/01/13/the-dunning%e2%80%93kruger-effect-and-you/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Long-term outlook for translation industry</title>
		<link>http://ginstrom.com/scribbles/2010/12/22/long-term-outlook-for-translation-industry/</link>
		<comments>http://ginstrom.com/scribbles/2010/12/22/long-term-outlook-for-translation-industry/#comments</comments>
		<pubDate>Wed, 22 Dec 2010 13:42:32 +0000</pubDate>
		<dc:creator>Ryan Ginstrom</dc:creator>
				<category><![CDATA[translation]]></category>

		<guid isPermaLink="false">http://ginstrom.com/scribbles/?p=1654</guid>
		<description><![CDATA[I recently read two books with rather gloomy outlooks for our future civilization: The Ecotechnic Future and The Long Descent. Both books predict that when the petroleum runs out, human civilization will go back to pre-industrial levels. While I don't necessarily agree with all the conclusions of these books, other than the obvious fact that [...]]]></description>
			<content:encoded><![CDATA[<p>I recently read two books with rather gloomy outlooks for our future civilization: <a href="http://www.amazon.com/Ecotechnic-Future-Envisioning-Post-Peak-World/dp/0865716390">The Ecotechnic Future</a> and <a href="http://www.amazon.com/Long-Descent-Users-Guide-Industrial/dp/0865716099">The Long Descent</a>. Both books predict that when the petroleum runs out, human civilization will go back to pre-industrial levels.</p>
<p>While I don't necessarily agree with all the conclusions of these books, other than the obvious fact that the oil and other resources are indeed running out, it got me thinking about the long-term future of the translation industry, going out 50 years or more.</p>
<p>I think that three factors will have the most impact on the translation industry over the rest of the century: decline of the United States as a superpower, artificial intelligence, and peak oil.</p>
<h3>End of United States Hegemony</h3>
<p>The global dominance of the US is in decline. As the dominance of the US declines, so will the dominance of English. Of course, there will be a lag, with English retaining its prestige for some time after US power fades, but in the end I think we'll see a much more multilingual world.</p>
<p>Currently, English is to a large extent <strong>the</strong> foreign language that is learned. One Italian engineer once told me, "English is not a language to study, it's a language to know." German or French you might study; you're expected to know English. </p>
<p>As a result, English is something of a lingua franca for translation, with English translations being made for non-native speakers of English. For example, multinational corporations will often translate their manuals into English only, and then use those in all locations worldwide.</p>
<p>For the case of Japanese as a source language, it's also fairly common for a document to be translated into English, and then from the English into other languages, even if the English translation will never be used. This is because it's apparently easier to find Japanese->English translators, and then translators from English to another language, than, say, a Japanese->Spanish translator.</p>
<p>The waning of US power will be followed by a decline in English. I think that the end result will be more overall translation, but somewhat less translation into or out of English. Instead of just creating English versions of documents, future clients will be forced to translate into many different languages; conversely, the role of English as a lingua franca or intermediary language will decline.</p>
<h3>AI</h3>
<p>Despite a continual tide of bold predictions, machine translation isn't appreciably better than it was 30 or even 40 years ago. The problem is that beyond a certain rudimentary level, the process of language translation requires the full intelligence of a human brain. This is why translation is an <a href="https://secure.wikimedia.org/wikipedia/en/wiki/AI-complete">AI-complete</a> problem. And general human intelligence has remained a far-off goal since the field of AI was invented.</p>
<p>But machines are getting inexorably more powerful, and consequently they're getting smarter as well. One by one, the cherished set of skills reserved to human intellect are being overtaken by computers.</p>
<p>In the 1990s, an IBM computer conquered the skill of chess. IBM is now attempting to <a href="http://news.yahoo.com/s/ap/us_tv_man_vs_machine;_ylt=As1.Apc2GC7hpYYRPI6YpR9H2ocA;_ylu=X3oDMTMydG5uMGd1BGFzc2V0Ay9zL2FwL3VzX3R2X21hbl92c19tYWNoaW5lBGNjb2RlA2dtcHJhbmRvbXIEY3BvcwM5BHBvcwM5BHNlYwN5bl90b3Bfc3RvcmllcwRzbGsDamVvcGFyZHl0b3Bp">do for Jeopardy</a> what it did for chess (<a href="http://www.youtube.com/watch?v=FC3IryWr4c8">Youtube video here</a>). Yes, this is just a mechanistic and rather simple-minded application of rules and data to simulate human trivia knowledge. On the other hand, it's getting us a lot closer, performance-wise, to the kind of general intelligence needed to perform tasks that are today "uniquely human." What will scientists be able to accomplish when computers are 10 times, 100 times, 1,000 times more powerful than today? (Yes, it seems certain that at least a 1,000-fold increase in performance will be possible, barring the end of modern civilization &#8212; see below)</p>
<p>It's entirely conceivable that computers will reach the level of general intelligence needed to perform translation as well as or better than human beings. The funny thing about general intelligence, however, is that it's <strong>general</strong>: such a computer could also perform surgery, write sonnets, and swindle little old ladies out of their pensions. If you think that's far-fetched, remember that even today, computers are driving cars on our streets, flying and landing airliners, diagnosing diseases, and performing scientific research.</p>
<p>It's very hard for me to picture what such a future society would look like. It would be nearly impossible for human labor to compete with machine labor &#8212; every job that can be done by a computer seems unavoidably destined to be performed by a computer.</p>
<p>Our current economic system would no longer function in a society where human labor has no value, and the only value was derived from the capital required to purchase computers and resources. Would it be a post-scarcity utopia, or a hell of marginal, meaningless existence for all those but the capital-owning elite?</p>
<h3>Peak Oil</h3>
<p>We probably reached <a href="https://secure.wikimedia.org/wikipedia/en/wiki/Peak_oil">peak oil</a> in 2005, and there is still no viable alternative source of energy to replace it. Since oil supplies will dwindle over the same curve that they rose, over the next century the price of oil will gradually increase, until it will be far too precious to burn in a combustion engine.</p>
<p>And that gives humanity a century to come up with alternative sources of energy. Unfortunately, demand for energy is currently rising, rather than falling. Even though rising energy prices will stimulate energy efficiency (global petroleum consumption fell by 15% during the oil crises of the 1970s), we're obviously going to need a lot of relatively cheap energy to keep modern society as we know it running.</p>
<p>The progress toward intelligent machines will depend greatly on how expensive energy is. If we succeed at creating a generally intelligent computer, but it consumes as much power as a small town, then depending on the price of energy, it might be more cost-effective to employ a town-full of people instead.</p>
<p>As energy grows more expensive, R&#038;D will also slow. A lot of our technology is also tied to cheap energy, from the machines used to extract resources, to the trucks used to transport them, to the factories used to make our shiny new widgets. Our technological future is therefore going to depend greatly on whether we can find alternative sources of energy that are cheap and plentiful enough to supply the energy required by our modern society.</p>
<p>Or course, translation was a viable profession long before the industrial revolution, so it will remain a viable profession no matter how energy-starved our future civilization becomes.</p>
<p>Translators will also do quite well in an eco-conservative future, where it is much cheaper and more efficient to move around information than widgets. Translation is quite amenable to remote work.</p>
<p>The only future scenario in which translation as a profession will end is one in which machines take over virtually every form of labor currently performed by humans. Thus as long as computers don't put us out of work entirely, there will be ample work for the translators of the future. And if computers do put us out of work, at least we'll have plenty of company.</p>
]]></content:encoded>
			<wfw:commentRss>http://ginstrom.com/scribbles/2010/12/22/long-term-outlook-for-translation-industry/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Setting contentEditable in a wxPython IEHtmlWindow</title>
		<link>http://ginstrom.com/scribbles/2010/12/19/setting-contenteditable-in-a-wxpython-iehtmlwindow/</link>
		<comments>http://ginstrom.com/scribbles/2010/12/19/setting-contenteditable-in-a-wxpython-iehtmlwindow/#comments</comments>
		<pubDate>Sun, 19 Dec 2010 05:38:09 +0000</pubDate>
		<dc:creator>Ryan Ginstrom</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://ginstrom.com/scribbles/?p=1687</guid>
		<description><![CDATA[wxPython's iewin.IEHtmlWindow lets you host the Internet Explorer browser control in a wxPython window. Doing so is quite simple: import wx from wx.lib import iewin class MyFrame&#40;wx.Frame&#41;: &#160; &#160; def __init__&#40;self&#41;: &#160; &#160; &#160; &#160; wx.Frame.__init__&#40;self, None, title=&#34;IEHtmlWindow&#34;&#41; &#160; &#160; &#160; &#160; self.ie = iewin.IEHtmlWindow&#40;self&#41; &#160; &#160; &#160; &#160; self.ie.Navigate&#40;&#34;http://example.com/&#34;&#41; # your URL here app [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.wxpython.org/">wxPython</a>'s iewin.IEHtmlWindow lets you host the Internet Explorer browser control in a wxPython window.</p>
<p>Doing so is quite simple:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">import</span> wx<br />
<span class="kw1">from</span> wx.<span class="me1">lib</span> <span class="kw1">import</span> iewin</p>
<p><span class="kw1">class</span> MyFrame<span class="br0">&#40;</span>wx.<span class="me1">Frame</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; wx.<span class="me1">Frame</span>.<span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>, <span class="kw2">None</span>, title=<span class="st0">&quot;IEHtmlWindow&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">ie</span> = iewin.<span class="me1">IEHtmlWindow</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">ie</span>.<span class="me1">Navigate</span><span class="br0">&#40;</span><span class="st0">&quot;http://example.com/&quot;</span><span class="br0">&#41;</span> <span class="co1"># your URL here</span></p>
<p>app = wx.<span class="me1">App</span><span class="br0">&#40;</span><span class="kw2">False</span><span class="br0">&#41;</span><br />
MyFrame<span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">Show</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p>app.<span class="me1">MainLoop</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div>
<p>IEHtmlWindow has a <code>ctrl</code> member that you can use to manipulate a page's DOM. One of the cool things that this allows you to do is edit a specific element on a page.</p>
<p>To do this, you first need to get the desired element:</p>
<div class="dean_ch" style="white-space: wrap;">element = <span class="kw2">self</span>.<span class="me1">ie</span>.<span class="me1">ctrl</span>.<span class="me1">Document</span>.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="st0">&quot;some_item_id&quot;</span><span class="br0">&#41;</span></div>
<p>And then set <code>contentEditable</code> to "true".</p>
<p>However, <code>getElementByID</code> returns an <a href="http://msdn.microsoft.com/en-us/library/aa752279%28v=vs.85%29.aspx">IHTMLElement</a> interface, and <code>contentEditable</code> is only supported by the <a href="http://msdn.microsoft.com/en-us/library/aa703950(VS.85).aspx">IHTMLElement3</a> interface and higher (IE has been around for a while, and there are now something like 6 iterations of this interface&#8230;). We therefore need to call <code>QueryInterface</code> on our element in order to get an IHTMLElement3.</p>
<p>The <code>QueryInterface</code> method call takes the class of the interface we want, which lives in the MSHTML module generated by <a href="http://sourceforge.net/projects/comtypes/">comtypes</a> (iewin ensures it's generated), so we need to import that.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">from</span> comtypes.<span class="me1">gen</span> <span class="kw1">import</span> MSHTML</div>
<p>Then, we get the IHTMLElement3 interface, and set <code>contentEditable</code> to "true" like this:</p>
<div class="dean_ch" style="white-space: wrap;">element = <span class="kw2">self</span>.<span class="me1">ie</span>.<span class="me1">ctrl</span>.<span class="me1">Document</span>.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="st0">&quot;my_element&quot;</span><span class="br0">&#41;</span><br />
element3 = element.<span class="me1">QueryInterface</span><span class="br0">&#40;</span>MSHTML.<span class="me1">IHTMLElement3</span><span class="br0">&#41;</span><br />
element3.<span class="me1">contentEditable</span> = <span class="st0">&quot;true&quot;</span></div>
<p>Since we can't manipulate the DOM until the document is loaded, it's a good idea to put this code in the <code>DocumentComplete</code> event handler (which we get called by setting ourselves as the event sink).</p>
<p>So putting it all together:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">import</span> wx<br />
<span class="kw1">from</span> wx.<span class="me1">lib</span> <span class="kw1">import</span> iewin<br />
<span class="kw1">from</span> comtypes.<span class="me1">gen</span> <span class="kw1">import</span> MSHTML</p>
<p><span class="kw1">class</span> MyFrame<span class="br0">&#40;</span>wx.<span class="me1">Frame</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Init IEHtmlWindow and set ourselves as event sink&quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; wx.<span class="me1">Frame</span>.<span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>, <span class="kw2">None</span>, title=<span class="st0">&quot;IEHtmlWindow&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">ie</span> = iewin.<span class="me1">IEHtmlWindow</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">ie</span>.<span class="me1">AddEventSink</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">ie</span>.<span class="me1">Navigate</span><span class="br0">&#40;</span><span class="st0">&quot;http://example.com/&quot;</span><span class="br0">&#41;</span> <span class="co1"># your URL here</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> DocumentComplete<span class="br0">&#40;</span><span class="kw2">self</span>, this, pDisp, URL<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Called when the HTML document finishes loading.<br />
&nbsp; &nbsp; &nbsp; &nbsp; If we were waiting on any actions to perform<br />
&nbsp; &nbsp; &nbsp; &nbsp; when the document was complete, we execute them here.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; element = <span class="kw2">self</span>.<span class="me1">ie</span>.<span class="me1">ctrl</span>.<span class="me1">Document</span>.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="st0">&quot;my_element&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; element3 = element.<span class="me1">QueryInterface</span><span class="br0">&#40;</span>MSHTML.<span class="me1">IHTMLElement3</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; element3.<span class="me1">contentEditable</span> = <span class="st0">&quot;true&quot;</span></p>
<p>app = wx.<span class="me1">App</span><span class="br0">&#40;</span><span class="kw2">False</span><span class="br0">&#41;</span><br />
MyFrame<span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">Show</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p>app.<span class="me1">MainLoop</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div>
<p>That's it. Not bad for 26 lines of code, including docstrings.</p>
]]></content:encoded>
			<wfw:commentRss>http://ginstrom.com/scribbles/2010/12/19/setting-contenteditable-in-a-wxpython-iehtmlwindow/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Some numbers</title>
		<link>http://ginstrom.com/scribbles/2010/12/17/some-numbers/</link>
		<comments>http://ginstrom.com/scribbles/2010/12/17/some-numbers/#comments</comments>
		<pubDate>Fri, 17 Dec 2010 03:47:54 +0000</pubDate>
		<dc:creator>Ryan Ginstrom</dc:creator>
				<category><![CDATA[freelancing]]></category>
		<category><![CDATA[translation]]></category>

		<guid isPermaLink="false">http://ginstrom.com/scribbles/?p=1679</guid>
		<description><![CDATA[A freelance translator's income can be calculated by the following formula: r * p * h * d * w where: r = rate p = pages per hour h = hour worked per day d = days worked per week w = weeks worked per year Let's try plugging in some numbers. Say that [...]]]></description>
			<content:encoded><![CDATA[<p>A freelance translator's income can be calculated by the following formula:</p>
<blockquote><p><em>r * p * h * d * w</em><br />
where:<br />
<em>r</em> = rate<br />
<em>p</em> = pages per hour<br />
<em>h</em> = hour worked per day<br />
<em>d</em> = days worked per week<br />
<em>w</em> = weeks worked per year
</p></blockquote>
<p>Let's try plugging in some numbers. Say that you charge $30 per page, you translate 2.5 pages per hour, you work 4 hours per day (that's actually optimistic for hours worked in a corporate environment), 5 days per week, and 50 weeks per year. Call this person Average Allie.</p>
<blockquote><p>Average Allie:<br />
$30 * 2.5 p * 4 h * 5 d * 50 w = $75,000</p></blockquote>
<p>Now, let's say you charge $40 per page, and translate 2 pages per hour, with time worked the same (Quality Quinton).</p>
<blockquote><p>Quality Quinton:<br />
$40 * 2 p * 4 h * 5 d * 50 w = $80,000</p></blockquote>
<p>Now, let's say you charge $30 per page, but translate 3 pages per hour (Fast Frank):</p>
<blockquote><p>Fast Frank:<br />
$30 * 3 p * 4 h * 5 d * 50 w = $90,000</p></blockquote>
<p>Curiously, it seems to generally be more lucrative to be fast than expensive.</p>
<p>How about people who work for very low rates ($10/page, or $0.05 word &#8212; certainly not unheard of), but work long hours (8 hours/day, no vacations) to make up for it? I'll also assume that they're not very fast (1 page/hour, because those charging the lowest rates are usually the least skilled, and the unskilled are usually slow too). Call this person Poor Peter.</p>
<blockquote><p>Poor Peter:<br />
$10 * 1 p * 8 h * 5 d * 52 w = $20,800</p></blockquote>
<p>When people say that it's impossible to make a living as a translator, I think that they must have a scenario like the one above in mind. </p>
<p>To me, it's pretty obvious that the way for people like Poor Peter to improve their incomes is not by working more (increasing the values of <em>h</em>, <em>d</em>, or <em>w</em>), but by becoming better translators, so that they can work faster (increasing <em>p</em>), and charge more (increasing <em>r</em>)</p>
]]></content:encoded>
			<wfw:commentRss>http://ginstrom.com/scribbles/2010/12/17/some-numbers/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Dear Steam: Geographical embargoes are stupid</title>
		<link>http://ginstrom.com/scribbles/2010/12/14/dear-steam-geographical-embargoes-are-stupid/</link>
		<comments>http://ginstrom.com/scribbles/2010/12/14/dear-steam-geographical-embargoes-are-stupid/#comments</comments>
		<pubDate>Tue, 14 Dec 2010 05:04:12 +0000</pubDate>
		<dc:creator>Ryan Ginstrom</dc:creator>
				<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://ginstrom.com/scribbles/?p=1666</guid>
		<description><![CDATA[At a time when piracy is putting a dent in video-game sales, Steam appears to be quite successful. Their success is due to two main factors: It's easier to buy a game on Steam than to pirate one Steam offers advantages over pirated apps When you buy a game from Steam, it automatically downloads to [...]]]></description>
			<content:encoded><![CDATA[<p>At a time when piracy is putting a dent in video-game sales, <a href="http://store.steampowered.com/">Steam</a> appears to be quite successful. Their success is due to two main factors:</p>
<ol>
<li>It's easier to buy a game on Steam than to pirate one</li>
<li>Steam offers advantages over pirated apps</li>
</ol>
<p>When you buy a game from Steam, it automatically downloads to your computer, and then you're ready to start playing. It eliminates most of the hassle of installing a new game (getting a refund if the game won't run, however, is something they need to work on).</p>
<p>And Steam offers some extras that pirates don't get, like access to an online gaming network.</p>
<p>So in short, Steam is successful because it removes all the friction that drives people to pirate, other than price. And that's why having geographical embargoes on games is so dumb.</p>
<p>Twice now, Steam has refused to sell me games because I live in Japan: once with Napoleon: Total War, and once with Civilization V.</p>
<div id="attachment_1667" class="wp-caption alignnone" style="width: 519px"><a href="http://ginstrom.com/scribbles/wp-content/uploads/2010/12/oops_sorry.png"><img src="http://ginstrom.com/scribbles/wp-content/uploads/2010/12/oops_sorry.png" alt="Oops, sorry!" title="oops_sorry" width="509" height="215" class="size-full wp-image-1667" /></a><p class="wp-caption-text">Oops, sorry!</p></div>
<p>Dear Steam: This is not the way to keep people from pirating your games. In fact, it's an almost perfect way to convince them to become pirates.</p>
<p>In most if not all cases, the geographical embargoes are mandated by the game publishers, and not by Steam. Japanese localization houses will sometimes require the publisher to give them exclusive rights to sales in Japan.</p>
<p>Back in the 1990s, giving up the rights to sales in Japan seemed like a good deal, since very few non-Japanese game publishers are able to handle selling in this country.</p>
<p>But this is a piss-poor excuse today, when you can sell in Japan through intermediaries like Amazon and Steam.</p>
<p>Steam, you have the clout to bop some sense into the game publishers. Convince them to let you sell their games worldwide, or face lost sales opportunities and a growing pirate population.</p>
]]></content:encoded>
			<wfw:commentRss>http://ginstrom.com/scribbles/2010/12/14/dear-steam-geographical-embargoes-are-stupid/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

