<div dir="ltr"><div>Nice !<br><br></div>Thank you !<br></div><div class="gmail_extra"><br><div class="gmail_quote">2015-12-24 9:00 GMT-02:00  <span dir="ltr">&lt;<a href="mailto:bf-docboard-request@blender.org" target="_blank">bf-docboard-request@blender.org</a>&gt;</span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Send Bf-docboard mailing list submissions to<br>
        <a href="mailto:bf-docboard@blender.org">bf-docboard@blender.org</a><br>
<br>
To subscribe or unsubscribe via the World Wide Web, visit<br>
        <a href="http://lists.blender.org/mailman/listinfo/bf-docboard" rel="noreferrer" target="_blank">http://lists.blender.org/mailman/listinfo/bf-docboard</a><br>
or, via email, send a message with subject or body &#39;help&#39; to<br>
        <a href="mailto:bf-docboard-request@blender.org">bf-docboard-request@blender.org</a><br>
<br>
You can reach the person managing the list at<br>
        <a href="mailto:bf-docboard-owner@blender.org">bf-docboard-owner@blender.org</a><br>
<br>
When replying, please edit your Subject line so it is more specific<br>
than &quot;Re: Contents of Bf-docboard digest...&quot;<br>
<br>
<br>
Today&#39;s Topics:<br>
<br>
   1. Translations Tracker (Anton Felix Lorenzen)<br>
   2. Re: Translations Tracker (Aaron Carlisle)<br>
   3. Re: Translations Tracker (Campbell Barton)<br>
<br>
<br>
----------------------------------------------------------------------<br>
<br>
Message: 1<br>
Date: Wed, 23 Dec 2015 19:11:11 +0100<br>
From: Anton Felix Lorenzen &lt;<a href="mailto:anfelor@web.de">anfelor@web.de</a>&gt;<br>
Subject: [Bf-docboard] Translations Tracker<br>
To: <a href="mailto:bf-docboard@blender.org">bf-docboard@blender.org</a><br>
Message-ID: &lt;<a href="mailto:567AE3BF.7040005@web.de">567AE3BF.7040005@web.de</a>&gt;<br>
Content-Type: text/plain; charset=utf-8<br>
<br>
Hi all,<br>
<br>
I re-wrote the script in python,<br>
it&#39;s now around 360 times as fast using python3<br>
(and even 675 times when using pypy).<br>
<br>
I overused grep before,<br>
so it took the script 9 minutes to finish,<br>
now it runs in approx. 1 second.<br>
<br>
It also shows files with fuzzy strings in it<br>
and should also run on windows.<br>
<br>
Sincerely,<br>
Anton Felix Lorenzen<br>
<br>
Usage:<br>
|- Paste into file named translations.py<br>
|- &quot;cd&quot; into folder<br>
|- execute python translations.py &quot;C:\path\to\LC_MESSAGES&quot;<br>
<br>
Script:<br>
<br>
#!/usr/bin/env python2<br>
# -*- coding: utf-8 -*-<br>
#<br>
#  Translations Tracker 1.0<br>
#  works best with pypy<br>
#<br>
#  Copyright 2015 Anton Felix Lorenzen &lt;<a href="mailto:anfelor@web.de">anfelor@web.de</a>&gt;<br>
#<br>
#  Permission is hereby granted, free of charge,<br>
#  to any person obtaining a copy of this software<br>
#  and associated documentation files (the &quot;Software&quot;),<br>
#  to deal in the Software without restriction,<br>
#  including without limitation the rights to use, copy,<br>
#  modify, merge, publish, distribute, sublicense,<br>
#  and/or sell copies of the Software,<br>
#  and to permit persons to whom the Software is furnished to do so,<br>
#  subject to the following conditions:<br>
#<br>
#  The above copyright notice and this permission notice<br>
#  shall be included in all copies or substantial portions of the Software.<br>
#<br>
#  THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND,<br>
#  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF<br>
MERCHANTABILITY,<br>
#  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.<br>
#  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY<br>
CLAIM,<br>
#  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,<br>
#  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE<br>
SOFTWARE<br>
#  OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.<br>
<br>
import os<br>
import codecs<br>
import sys<br>
<br>
if(sys.argv and sys.argv[1]):<br>
        path = sys.argv[1]<br>
else:<br>
        path = &quot;~/locale/fr/LC_MESSAGES&quot;<br>
<br>
# Configuration<br>
fileinfo  = &#39;{0[file]:&gt;3} empty, {1[file]:&gt;3} fuzzy of {2[file]:&gt;3}; or<br>
{3:.3f}% in {4}&#39;<br>
allinfo   = &#39;Summary: {0[all]} empty of {1[all]}; or {2:.3f}%&#39;<br>
fuzzyinfo = &#39;Fuzzy:   {0[all]} fuzzy strings in {0[filelist]}&#39;<br>
<br>
msgstrs = {&#39;file&#39;: 0, &#39;all&#39;:0}<br>
empty_msgstrs = {&#39;file&#39;: 0, &#39;all&#39;: 0}<br>
fuzzy = {&#39;file&#39;: 0, &#39;all&#39;: 0, &#39;filelist&#39;: []}<br>
lastLineWasEmptyMsgstr = False<br>
<br>
def forAllInMap(m, fnk, cond):<br>
        for key in m:<br>
                if(cond(m[key])):<br>
                        m[key] = fnk(m[key])<br>
<br>
def forAllIntsInMap(m, fnk):<br>
        forAllInMap(m, fnk, lambda x: type(x)==int)<br>
<br>
def increaseAllInMap(m):<br>
        forAllIntsInMap(m, lambda x: x+1)<br>
<br>
def decreseAllInMap(m):<br>
        forAllIntsInMap(m, lambda x: x-1)<br>
<br>
for (root, subs, files) in os.walk(path):<br>
        for name in files:<br>
                msgstrs[&#39;file&#39;] = -1 # First lines contain a &quot;fake&quot; msgstr<br>
                msgstrs[&#39;all&#39;] -= 1<br>
                empty_msgstrs[&#39;file&#39;] = 0<br>
                fuzzy[&#39;file&#39;] = 0<br>
                if name.endswith(&#39;.po&#39;):<br>
                        for line in codecs.open(os.path.join(root, name), encoding=&#39;utf8&#39;):<br>
                                if(line[0] == &#39;m&#39;):<br>
                                        if(line[0:6] == &#39;msgstr&#39;):<br>
                                                increaseAllInMap(msgstrs)<br>
                                                if(line[0:9] == &#39;msgstr &quot;&quot;&#39;):<br>
                                                        increaseAllInMap(empty_msgstrs)<br>
                                                        lastLineWasEmptyMsgstr = True<br>
                                else:<br>
                                        if(line[0] == &#39;&quot;&#39;):<br>
                                                if(lastLineWasEmptyMsgstr):<br>
                                                        decreseAllInMap(empty_msgstrs)<br>
                                                        lastLineWasEmptyMsgstr = False<br>
                                        else:<br>
                                                lastLineWasEmptyMsgstr = False<br>
                                                if(&#39;fuzzy&#39; in line):<br>
                                                        increaseAllInMap(fuzzy)<br>
                                                        fuzzy[&#39;filelist&#39;] += [name]<br>
<br>
                print(fileinfo.format(empty_msgstrs, fuzzy, msgstrs,<br>
                        float(empty_msgstrs[&#39;file&#39;] + fuzzy[&#39;file&#39;]) / msgstrs[&#39;file&#39;],<br>
                        os.path.join(root[len(path):], name)))<br>
<br>
print(allinfo.format(empty_msgstrs, msgstrs, float(empty_msgstrs[&#39;all&#39;])<br>
/ msgstrs[&#39;all&#39;]))<br>
print(fuzzyinfo.format(fuzzy))<br>
<br>
<br>
------------------------------<br>
<br>
Message: 2<br>
Date: Wed, 23 Dec 2015 18:39:42 -0500<br>
From: Aaron Carlisle &lt;<a href="mailto:carlisle.aaron00@gmail.com">carlisle.aaron00@gmail.com</a>&gt;<br>
Subject: Re: [Bf-docboard] Translations Tracker<br>
To: Blender Documentation Project &lt;<a href="mailto:bf-docboard@blender.org">bf-docboard@blender.org</a>&gt;<br>
Message-ID:<br>
        &lt;CAEX7TpVYsKMaCtoh4=<a href="mailto:BmAb2o7VMSO0_oiWcJ3i_kFbtjBobF%2Bw@mail.gmail.com">BmAb2o7VMSO0_oiWcJ3i_kFbtjBobF+w@mail.gmail.com</a>&gt;<br>
Content-Type: text/plain; charset=&quot;utf-8&quot;<br>
<br>
We may want to include this in trunk like we do with other .py tools in the<br>
main documentation repository, now that it is in python and everyone is<br>
able to use it.<br>
<br>
On Wed, Dec 23, 2015 at 1:11 PM, Anton Felix Lorenzen &lt;<a href="mailto:anfelor@web.de">anfelor@web.de</a>&gt;<br>
wrote:<br>
<br>
&gt; Hi all,<br>
&gt;<br>
&gt; I re-wrote the script in python,<br>
&gt; it&#39;s now around 360 times as fast using python3<br>
&gt; (and even 675 times when using pypy).<br>
&gt;<br>
&gt; I overused grep before,<br>
&gt; so it took the script 9 minutes to finish,<br>
&gt; now it runs in approx. 1 second.<br>
&gt;<br>
&gt; It also shows files with fuzzy strings in it<br>
&gt; and should also run on windows.<br>
&gt;<br>
&gt; Sincerely,<br>
&gt; Anton Felix Lorenzen<br>
&gt;<br>
&gt; Usage:<br>
&gt; |- Paste into file named translations.py<br>
&gt; |- &quot;cd&quot; into folder<br>
&gt; |- execute python translations.py &quot;C:\path\to\LC_MESSAGES&quot;<br>
&gt;<br>
&gt; Script:<br>
&gt;<br>
&gt; #!/usr/bin/env python2<br>
&gt; # -*- coding: utf-8 -*-<br>
&gt; #<br>
&gt; #  Translations Tracker 1.0<br>
&gt; #  works best with pypy<br>
&gt; #<br>
&gt; #  Copyright 2015 Anton Felix Lorenzen &lt;<a href="mailto:anfelor@web.de">anfelor@web.de</a>&gt;<br>
&gt; #<br>
&gt; #  Permission is hereby granted, free of charge,<br>
&gt; #  to any person obtaining a copy of this software<br>
&gt; #  and associated documentation files (the &quot;Software&quot;),<br>
&gt; #  to deal in the Software without restriction,<br>
&gt; #  including without limitation the rights to use, copy,<br>
&gt; #  modify, merge, publish, distribute, sublicense,<br>
&gt; #  and/or sell copies of the Software,<br>
&gt; #  and to permit persons to whom the Software is furnished to do so,<br>
&gt; #  subject to the following conditions:<br>
&gt; #<br>
&gt; #  The above copyright notice and this permission notice<br>
&gt; #  shall be included in all copies or substantial portions of the Software.<br>
&gt; #<br>
&gt; #  THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND,<br>
&gt; #  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF<br>
&gt; MERCHANTABILITY,<br>
&gt; #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.<br>
&gt; #  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY<br>
&gt; CLAIM,<br>
&gt; #  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,<br>
&gt; #  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE<br>
&gt; SOFTWARE<br>
&gt; #  OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.<br>
&gt;<br>
&gt; import os<br>
&gt; import codecs<br>
&gt; import sys<br>
&gt;<br>
&gt; if(sys.argv and sys.argv[1]):<br>
&gt;         path = sys.argv[1]<br>
&gt; else:<br>
&gt;         path = &quot;~/locale/fr/LC_MESSAGES&quot;<br>
&gt;<br>
&gt; # Configuration<br>
&gt; fileinfo  = &#39;{0[file]:&gt;3} empty, {1[file]:&gt;3} fuzzy of {2[file]:&gt;3}; or<br>
&gt; {3:.3f}% in {4}&#39;<br>
&gt; allinfo   = &#39;Summary: {0[all]} empty of {1[all]}; or {2:.3f}%&#39;<br>
&gt; fuzzyinfo = &#39;Fuzzy:   {0[all]} fuzzy strings in {0[filelist]}&#39;<br>
&gt;<br>
&gt; msgstrs = {&#39;file&#39;: 0, &#39;all&#39;:0}<br>
&gt; empty_msgstrs = {&#39;file&#39;: 0, &#39;all&#39;: 0}<br>
&gt; fuzzy = {&#39;file&#39;: 0, &#39;all&#39;: 0, &#39;filelist&#39;: []}<br>
&gt; lastLineWasEmptyMsgstr = False<br>
&gt;<br>
&gt; def forAllInMap(m, fnk, cond):<br>
&gt;         for key in m:<br>
&gt;                 if(cond(m[key])):<br>
&gt;                         m[key] = fnk(m[key])<br>
&gt;<br>
&gt; def forAllIntsInMap(m, fnk):<br>
&gt;         forAllInMap(m, fnk, lambda x: type(x)==int)<br>
&gt;<br>
&gt; def increaseAllInMap(m):<br>
&gt;         forAllIntsInMap(m, lambda x: x+1)<br>
&gt;<br>
&gt; def decreseAllInMap(m):<br>
&gt;         forAllIntsInMap(m, lambda x: x-1)<br>
&gt;<br>
&gt; for (root, subs, files) in os.walk(path):<br>
&gt;         for name in files:<br>
&gt;                 msgstrs[&#39;file&#39;] = -1 # First lines contain a &quot;fake&quot; msgstr<br>
&gt;                 msgstrs[&#39;all&#39;] -= 1<br>
&gt;                 empty_msgstrs[&#39;file&#39;] = 0<br>
&gt;                 fuzzy[&#39;file&#39;] = 0<br>
&gt;                 if name.endswith(&#39;.po&#39;):<br>
&gt;                         for line in codecs.open(os.path.join(root, name),<br>
&gt; encoding=&#39;utf8&#39;):<br>
&gt;                                 if(line[0] == &#39;m&#39;):<br>
&gt;                                         if(line[0:6] == &#39;msgstr&#39;):<br>
&gt;                                                 increaseAllInMap(msgstrs)<br>
&gt;                                                 if(line[0:9] == &#39;msgstr<br>
&gt; &quot;&quot;&#39;):<br>
&gt;<br>
&gt; increaseAllInMap(empty_msgstrs)<br>
&gt;<br>
&gt; lastLineWasEmptyMsgstr = True<br>
&gt;                                 else:<br>
&gt;                                         if(line[0] == &#39;&quot;&#39;):<br>
&gt;                                                 if(lastLineWasEmptyMsgstr):<br>
&gt;<br>
&gt; decreseAllInMap(empty_msgstrs)<br>
&gt;<br>
&gt; lastLineWasEmptyMsgstr = False<br>
&gt;                                         else:<br>
&gt;                                                 lastLineWasEmptyMsgstr =<br>
&gt; False<br>
&gt;                                                 if(&#39;fuzzy&#39; in line):<br>
&gt;<br>
&gt; increaseAllInMap(fuzzy)<br>
&gt;                                                         fuzzy[&#39;filelist&#39;]<br>
&gt; += [name]<br>
&gt;<br>
&gt;                 print(fileinfo.format(empty_msgstrs, fuzzy, msgstrs,<br>
&gt;                         float(empty_msgstrs[&#39;file&#39;] + fuzzy[&#39;file&#39;]) /<br>
&gt; msgstrs[&#39;file&#39;],<br>
&gt;                         os.path.join(root[len(path):], name)))<br>
&gt;<br>
&gt; print(allinfo.format(empty_msgstrs, msgstrs, float(empty_msgstrs[&#39;all&#39;])<br>
&gt; / msgstrs[&#39;all&#39;]))<br>
&gt; print(fuzzyinfo.format(fuzzy))<br>
&gt; _______________________________________________<br>
&gt; Bf-docboard mailing list<br>
&gt; <a href="mailto:Bf-docboard@blender.org">Bf-docboard@blender.org</a><br>
&gt; <a href="http://lists.blender.org/mailman/listinfo/bf-docboard" rel="noreferrer" target="_blank">http://lists.blender.org/mailman/listinfo/bf-docboard</a><br>
&gt;<br>
-------------- next part --------------<br>
An HTML attachment was scrubbed...<br>
URL: <a href="http://lists.blender.org/pipermail/bf-docboard/attachments/20151223/29230808/attachment.html" rel="noreferrer" target="_blank">http://lists.blender.org/pipermail/bf-docboard/attachments/20151223/29230808/attachment.html</a><br>
<br>
------------------------------<br>
<br>
Message: 3<br>
Date: Thu, 24 Dec 2015 13:49:39 +1100<br>
From: Campbell Barton &lt;<a href="mailto:ideasman42@gmail.com">ideasman42@gmail.com</a>&gt;<br>
Subject: Re: [Bf-docboard] Translations Tracker<br>
To: Blender Documentation Project &lt;<a href="mailto:bf-docboard@blender.org">bf-docboard@blender.org</a>&gt;<br>
Message-ID:<br>
        &lt;CAEcf3NztKz6fvQrktgZqH37hndXnjux49OogKBYnR_=<a href="mailto:dHJ0VZQ@mail.gmail.com">dHJ0VZQ@mail.gmail.com</a>&gt;<br>
Content-Type: text/plain; charset=UTF-8<br>
<br>
Tools like this are handy to keep in our repos.<br>
<br>
Made some changes:<br>
- Show percentages from 0-100, 100 when complete.<br>
- Use argparse for argument handling.<br>
- Add a --quiet option to only report the summary.<br>
- Avoid dictionary access for typical vars.<br>
- Use a set for listing fuzzy files (not to print then many times)<br>
- Move strings for reporting inline.<br>
- Can take multiple path arguments (report for each language).<br>
- Take report as an argument,<br>
  (to override print if we want to use multi-processing later).<br>
<br>
Gives overall 6x speedup here,<br>
<br>
Committed <a href="https://developer.blender.org/rBM1029" rel="noreferrer" target="_blank">https://developer.blender.org/rBM1029</a><br>
<br>
On Thu, Dec 24, 2015 at 10:39 AM, Aaron Carlisle<br>
&lt;<a href="mailto:carlisle.aaron00@gmail.com">carlisle.aaron00@gmail.com</a>&gt; wrote:<br>
&gt; We may want to include this in trunk like we do with other .py tools in the<br>
&gt; main documentation repository, now that it is in python and everyone is able<br>
&gt; to use it.<br>
&gt;<br>
&gt; On Wed, Dec 23, 2015 at 1:11 PM, Anton Felix Lorenzen &lt;<a href="mailto:anfelor@web.de">anfelor@web.de</a>&gt;<br>
&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; Hi all,<br>
&gt;&gt;<br>
&gt;&gt; I re-wrote the script in python,<br>
&gt;&gt; it&#39;s now around 360 times as fast using python3<br>
&gt;&gt; (and even 675 times when using pypy).<br>
&gt;&gt;<br>
&gt;&gt; I overused grep before,<br>
&gt;&gt; so it took the script 9 minutes to finish,<br>
&gt;&gt; now it runs in approx. 1 second.<br>
&gt;&gt;<br>
&gt;&gt; It also shows files with fuzzy strings in it<br>
&gt;&gt; and should also run on windows.<br>
&gt;&gt;<br>
&gt;&gt; Sincerely,<br>
&gt;&gt; Anton Felix Lorenzen<br>
&gt;&gt;<br>
&gt;&gt; Usage:<br>
&gt;&gt; |- Paste into file named translations.py<br>
&gt;&gt; |- &quot;cd&quot; into folder<br>
&gt;&gt; |- execute python translations.py &quot;C:\path\to\LC_MESSAGES&quot;<br>
&gt;&gt;<br>
&gt;&gt; Script:<br>
&gt;&gt;<br>
&gt;&gt; #!/usr/bin/env python2<br>
&gt;&gt; # -*- coding: utf-8 -*-<br>
&gt;&gt; #<br>
&gt;&gt; #  Translations Tracker 1.0<br>
&gt;&gt; #  works best with pypy<br>
&gt;&gt; #<br>
&gt;&gt; #  Copyright 2015 Anton Felix Lorenzen &lt;<a href="mailto:anfelor@web.de">anfelor@web.de</a>&gt;<br>
&gt;&gt; #<br>
&gt;&gt; #  Permission is hereby granted, free of charge,<br>
&gt;&gt; #  to any person obtaining a copy of this software<br>
&gt;&gt; #  and associated documentation files (the &quot;Software&quot;),<br>
&gt;&gt; #  to deal in the Software without restriction,<br>
&gt;&gt; #  including without limitation the rights to use, copy,<br>
&gt;&gt; #  modify, merge, publish, distribute, sublicense,<br>
&gt;&gt; #  and/or sell copies of the Software,<br>
&gt;&gt; #  and to permit persons to whom the Software is furnished to do so,<br>
&gt;&gt; #  subject to the following conditions:<br>
&gt;&gt; #<br>
&gt;&gt; #  The above copyright notice and this permission notice<br>
&gt;&gt; #  shall be included in all copies or substantial portions of the<br>
&gt;&gt; Software.<br>
&gt;&gt; #<br>
&gt;&gt; #  THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND,<br>
&gt;&gt; #  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF<br>
&gt;&gt; MERCHANTABILITY,<br>
&gt;&gt; #  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.<br>
&gt;&gt; #  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY<br>
&gt;&gt; CLAIM,<br>
&gt;&gt; #  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,<br>
&gt;&gt; #  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE<br>
&gt;&gt; SOFTWARE<br>
&gt;&gt; #  OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.<br>
&gt;&gt;<br>
&gt;&gt; import os<br>
&gt;&gt; import codecs<br>
&gt;&gt; import sys<br>
&gt;&gt;<br>
&gt;&gt; if(sys.argv and sys.argv[1]):<br>
&gt;&gt;         path = sys.argv[1]<br>
&gt;&gt; else:<br>
&gt;&gt;         path = &quot;~/locale/fr/LC_MESSAGES&quot;<br>
&gt;&gt;<br>
&gt;&gt; # Configuration<br>
&gt;&gt; fileinfo  = &#39;{0[file]:&gt;3} empty, {1[file]:&gt;3} fuzzy of {2[file]:&gt;3}; or<br>
&gt;&gt; {3:.3f}% in {4}&#39;<br>
&gt;&gt; allinfo   = &#39;Summary: {0[all]} empty of {1[all]}; or {2:.3f}%&#39;<br>
&gt;&gt; fuzzyinfo = &#39;Fuzzy:   {0[all]} fuzzy strings in {0[filelist]}&#39;<br>
&gt;&gt;<br>
&gt;&gt; msgstrs = {&#39;file&#39;: 0, &#39;all&#39;:0}<br>
&gt;&gt; empty_msgstrs = {&#39;file&#39;: 0, &#39;all&#39;: 0}<br>
&gt;&gt; fuzzy = {&#39;file&#39;: 0, &#39;all&#39;: 0, &#39;filelist&#39;: []}<br>
&gt;&gt; lastLineWasEmptyMsgstr = False<br>
&gt;&gt;<br>
&gt;&gt; def forAllInMap(m, fnk, cond):<br>
&gt;&gt;         for key in m:<br>
&gt;&gt;                 if(cond(m[key])):<br>
&gt;&gt;                         m[key] = fnk(m[key])<br>
&gt;&gt;<br>
&gt;&gt; def forAllIntsInMap(m, fnk):<br>
&gt;&gt;         forAllInMap(m, fnk, lambda x: type(x)==int)<br>
&gt;&gt;<br>
&gt;&gt; def increaseAllInMap(m):<br>
&gt;&gt;         forAllIntsInMap(m, lambda x: x+1)<br>
&gt;&gt;<br>
&gt;&gt; def decreseAllInMap(m):<br>
&gt;&gt;         forAllIntsInMap(m, lambda x: x-1)<br>
&gt;&gt;<br>
&gt;&gt; for (root, subs, files) in os.walk(path):<br>
&gt;&gt;         for name in files:<br>
&gt;&gt;                 msgstrs[&#39;file&#39;] = -1 # First lines contain a &quot;fake&quot; msgstr<br>
&gt;&gt;                 msgstrs[&#39;all&#39;] -= 1<br>
&gt;&gt;                 empty_msgstrs[&#39;file&#39;] = 0<br>
&gt;&gt;                 fuzzy[&#39;file&#39;] = 0<br>
&gt;&gt;                 if name.endswith(&#39;.po&#39;):<br>
&gt;&gt;                         for line in codecs.open(os.path.join(root, name),<br>
&gt;&gt; encoding=&#39;utf8&#39;):<br>
&gt;&gt;                                 if(line[0] == &#39;m&#39;):<br>
&gt;&gt;                                         if(line[0:6] == &#39;msgstr&#39;):<br>
&gt;&gt;                                                 increaseAllInMap(msgstrs)<br>
&gt;&gt;                                                 if(line[0:9] == &#39;msgstr<br>
&gt;&gt; &quot;&quot;&#39;):<br>
&gt;&gt;<br>
&gt;&gt; increaseAllInMap(empty_msgstrs)<br>
&gt;&gt;<br>
&gt;&gt; lastLineWasEmptyMsgstr = True<br>
&gt;&gt;                                 else:<br>
&gt;&gt;                                         if(line[0] == &#39;&quot;&#39;):<br>
&gt;&gt;<br>
&gt;&gt; if(lastLineWasEmptyMsgstr):<br>
&gt;&gt;<br>
&gt;&gt; decreseAllInMap(empty_msgstrs)<br>
&gt;&gt;<br>
&gt;&gt; lastLineWasEmptyMsgstr = False<br>
&gt;&gt;                                         else:<br>
&gt;&gt;                                                 lastLineWasEmptyMsgstr =<br>
&gt;&gt; False<br>
&gt;&gt;                                                 if(&#39;fuzzy&#39; in line):<br>
&gt;&gt;<br>
&gt;&gt; increaseAllInMap(fuzzy)<br>
&gt;&gt;                                                         fuzzy[&#39;filelist&#39;]<br>
&gt;&gt; += [name]<br>
&gt;&gt;<br>
&gt;&gt;                 print(fileinfo.format(empty_msgstrs, fuzzy, msgstrs,<br>
&gt;&gt;                         float(empty_msgstrs[&#39;file&#39;] + fuzzy[&#39;file&#39;]) /<br>
&gt;&gt; msgstrs[&#39;file&#39;],<br>
&gt;&gt;                         os.path.join(root[len(path):], name)))<br>
&gt;&gt;<br>
&gt;&gt; print(allinfo.format(empty_msgstrs, msgstrs, float(empty_msgstrs[&#39;all&#39;])<br>
&gt;&gt; / msgstrs[&#39;all&#39;]))<br>
&gt;&gt; print(fuzzyinfo.format(fuzzy))<br>
&gt;&gt; _______________________________________________<br>
&gt;&gt; Bf-docboard mailing list<br>
&gt;&gt; <a href="mailto:Bf-docboard@blender.org">Bf-docboard@blender.org</a><br>
&gt;&gt; <a href="http://lists.blender.org/mailman/listinfo/bf-docboard" rel="noreferrer" target="_blank">http://lists.blender.org/mailman/listinfo/bf-docboard</a><br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; _______________________________________________<br>
&gt; Bf-docboard mailing list<br>
&gt; <a href="mailto:Bf-docboard@blender.org">Bf-docboard@blender.org</a><br>
&gt; <a href="http://lists.blender.org/mailman/listinfo/bf-docboard" rel="noreferrer" target="_blank">http://lists.blender.org/mailman/listinfo/bf-docboard</a><br>
&gt;<br>
<br>
<br>
<br>
--<br>
- Campbell<br>
<br>
<br>
------------------------------<br>
<br>
_______________________________________________<br>
Bf-docboard mailing list<br>
<a href="mailto:Bf-docboard@blender.org">Bf-docboard@blender.org</a><br>
<a href="http://lists.blender.org/mailman/listinfo/bf-docboard" rel="noreferrer" target="_blank">http://lists.blender.org/mailman/listinfo/bf-docboard</a><br>
<br>
<br>
End of Bf-docboard Digest, Vol 130, Issue 10<br>
********************************************<br>
</blockquote></div><br></div>