<?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>Teknik | Daniel Nylander.se</title>
	<atom:link href="https://www.danielnylander.se/category/teknik/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.danielnylander.se</link>
	<description>Svenska översättningar av öppen källkod, Ubuntu, Debian, Translation Project, GNU, Linux, UNIX, VoIP, IT-Säkerhet, emulatorer, tv-spel, experiment, väl valda ord och delvis sinnesnärvaro</description>
	<lastBuildDate>Tue, 31 Mar 2026 14:24:11 +0000</lastBuildDate>
	<language>sv-SE</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://i0.wp.com/www.danielnylander.se/wp-content/cropped-danne.jpg?fit=32%2C32&#038;ssl=1</url>
	<title>Teknik | Daniel Nylander.se</title>
	<link>https://www.danielnylander.se</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">87370683</site>	<item>
		<title>Zabbix, Wazuh, Zrythm och pipeline-fixes — en dag med infra och i18n</title>
		<link>https://www.danielnylander.se/2026/03/31/zabbix-wazuh-zrythm-och-pipeline-fixes-en-dag-med-infra-och-i18n/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=zabbix-wazuh-zrythm-och-pipeline-fixes-en-dag-med-infra-och-i18n</link>
					<comments>https://www.danielnylander.se/2026/03/31/zabbix-wazuh-zrythm-och-pipeline-fixes-en-dag-med-infra-och-i18n/#respond</comments>
		
		<dc:creator><![CDATA[Daniel Nylander]]></dc:creator>
		<pubDate>Tue, 31 Mar 2026 14:24:10 +0000</pubDate>
				<category><![CDATA[Översättningar]]></category>
		<category><![CDATA[Teknik]]></category>
		<category><![CDATA[översättning]]></category>
		<category><![CDATA[FOSS]]></category>
		<category><![CDATA[i18n]]></category>
		<category><![CDATA[l10n]]></category>
		<category><![CDATA[svenska]]></category>
		<guid isPermaLink="false">https://www.danielnylander.se/?p=1957</guid>

					<description><![CDATA[<p>En fullspäckad dag med allt från infrastruktur till översättningar. Här är sammanfattningen. Zabbix — Fullständig monitoreringsinfrastruktur Distribuerade Zabbix 7.4 till 10 hostar — allt från Proxmox-noder och LXC-containrar till Mac Mini och WSL-maskiner. 10 hostar registrerade med agent2/agentd: Fixade: PHP 8.4 pgsql-modul, Admin-lockout, NVIDIA GPU-plugin-krasch Dashboard Wazuh — Uppgradering och i18n Dessutom: första svenska översättningen [&#8230;]</p>
<p>The post <a href="https://www.danielnylander.se/2026/03/31/zabbix-wazuh-zrythm-och-pipeline-fixes-en-dag-med-infra-och-i18n/">Zabbix, Wazuh, Zrythm och pipeline-fixes — en dag med infra och i18n</a> first appeared on <a href="https://www.danielnylander.se">Daniel Nylander.se</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>En fullspäckad dag med allt från infrastruktur till översättningar. Här är sammanfattningen.</p>
<h2>Zabbix — Fullständig monitoreringsinfrastruktur</h2>
<p>Distribuerade <strong>Zabbix 7.4</strong> till 10 hostar — allt från Proxmox-noder och LXC-containrar till Mac Mini och WSL-maskiner.</p>
<ul>
<li><strong>10 hostar registrerade</strong> med agent2/agentd:</li>
<li>Fixade: PHP 8.4 pgsql-modul, Admin-lockout, NVIDIA GPU-plugin-krasch</li>
<li>Dashboard</li>
</ul>
<h2>Wazuh — Uppgradering och i18n</h2>
<p>Dessutom: första svenska översättningen av <strong>Wazuh Dashboard</strong>.</p>
<ul>
<li><a href="https://github.com/wazuh/wazuh-dashboard-plugins/pull/8260">PR #8260</a> — 350 strängar i sv-SE.json</li>
<li>78 React-komponenter internationaliserade med <code>@osd/i18n</code></li>
<li>0 kvarvarande hårdkodade strängar</li>
<li>Första icke-engelska locale-bidraget till Wazuh</li>
</ul>
<h2>Zrythm — Från 63% till 99.9%</h2>
<p><a href="https://hosted.weblate.org/projects/zrythm/zrythm/sv/">Zrythm</a> (digital audio workstation) gick från <strong>63% till 99.9%</strong> svenska på en eftermiddag.</p>
<table>
<tbody>
<tr>
<th>Komponent</th>
<th>Före</th>
<th>Efter</th>
<th>Strängar</th>
</tr>
<tr>
<td>zrythm (app)</td>
<td>63%</td>
<td>99.9%</td>
<td>569 nya</td>
</tr>
<tr>
<td>web</td>
<td>13%</td>
<td>77%</td>
<td>178 nya</td>
</tr>
<tr>
<td>accounts</td>
<td>50%</td>
<td>81%</td>
<td>26 nya</td>
</tr>
<tr>
<td>user-manual</td>
<td>8%</td>
<td>89%</td>
<td>1 408 nya</td>
</tr>
</tbody>
</table>
<p>Totalt: <strong>2 181 strängar</strong> översatta och uppladdade till Weblate.</p>
<p>Hittade också en <a href="https://gitlab.zrythm.org/zrythm/zrythm/-/work_items/5242">segfault-bugg</a> i Zrythm — appen kraschar vid svenska locale pga en trasig format-sträng i den medföljande .mo-filen (4 av 5 <code>%s</code>-platshållare → <code>g_strdup_printf</code> segfaultar).</p>
<h2>review-po-v3 — Pipeline-förbättringar</h2>
<p>Fem uppdateringar baserade på dagens arbete:</p>
<ul>
<li><strong>ts2po-artefakter</strong> — filtrerar bort false positives från Qt TS → PO-konvertering (317 → 38 FAIL)</li>
<li><strong>Översatta platshållare</strong> — detekterar när sub-agenter översätter <code>{endref}</code> → <code>{slutref}</code></li>
<li><strong>&#8221;Vänligen&#8221; auto-fix</strong> — automatisk borttagning av DeepL:s bokstavliga &#8221;Please&#8221;-översättning</li>
<li><strong>DAW/musik-termer</strong> i brand-skip — plugin, fader, mixer, channel etc. flaggas inte längre som egennamn</li>
<li><strong>DevOps/security-termer</strong> — dashboard, agent, endpoint, compliance etc. i whitelisten</li>
</ul>
<h2>parallel-worker — Filformat-validering</h2>
<p>Patchade TR:s parallel-worker med validering som fångar felaktiga filer <em>innan</em> de kraschar review-po-v3:</p>
<ul>
<li>ZIP-arkiv, JSON, XML/Qt TS, binärfiler — alla avvisas med tydligt felmeddelande</li>
<li>30 error-jobb i kön → 23 återhämtade efter omstart</li>
</ul>
<h2>Siffror</h2>
<table>
<tbody>
<tr>
<th>Kategori</th>
<th>Antal</th>
</tr>
<tr>
<td>Strängar översatta (Zrythm)</td>
<td>2 181</td>
</tr>
<tr>
<td>Strängar översatta (Wazuh)</td>
<td>350</td>
</tr>
<tr>
<td>React-komponenter i18n (Wazuh)</td>
<td>78</td>
</tr>
<tr>
<td>Zabbix-hostar deployade</td>
<td>10</td>
</tr>
<tr>
<td>Wazuh uppgraderad</td>
<td>4.11.2 → 4.14.4</td>
</tr>
<tr>
<td>Buggar rapporterade</td>
<td>1 (Zrythm segfault)</td>
</tr>
<tr>
<td>Pipeline-förbättringar</td>
<td>5</td>
</tr>
<tr>
<td>PR:ar</td>
<td>1 (Wazuh #8260)</td>
</tr>
</tbody>
</table><p>The post <a href="https://www.danielnylander.se/2026/03/31/zabbix-wazuh-zrythm-och-pipeline-fixes-en-dag-med-infra-och-i18n/">Zabbix, Wazuh, Zrythm och pipeline-fixes — en dag med infra och i18n</a> first appeared on <a href="https://www.danielnylander.se">Daniel Nylander.se</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.danielnylander.se/2026/03/31/zabbix-wazuh-zrythm-och-pipeline-fixes-en-dag-med-infra-och-i18n/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1957</post-id>	</item>
		<item>
		<title>Visio Viewer: A Chrome Extension That Opens .vsdx Files — No Visio Required</title>
		<link>https://www.danielnylander.se/2026/03/01/visio-viewer-a-chrome-extension-that-opens-vsdx-files-no-visio-required/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=visio-viewer-a-chrome-extension-that-opens-vsdx-files-no-visio-required</link>
					<comments>https://www.danielnylander.se/2026/03/01/visio-viewer-a-chrome-extension-that-opens-vsdx-files-no-visio-required/#respond</comments>
		
		<dc:creator><![CDATA[Daniel Nylander]]></dc:creator>
		<pubDate>Sun, 01 Mar 2026 16:16:09 +0000</pubDate>
				<category><![CDATA[Teknik]]></category>
		<category><![CDATA[Verktyg]]></category>
		<category><![CDATA[chrome-extension]]></category>
		<category><![CDATA[libvisio-ng]]></category>
		<category><![CDATA[pyodide]]></category>
		<category><![CDATA[visio]]></category>
		<category><![CDATA[webassembly]]></category>
		<guid isPermaLink="false">https://www.danielnylander.se/2026/03/01/visio-viewer-a-chrome-extension-that-opens-vsdx-files-no-visio-required/</guid>

					<description><![CDATA[<p>Ever received a .vsdx file and had no way to open it? Microsoft Visio is expensive, Windows-only, and most online converters want you to upload your diagrams to some random server. There had to be a better way. So I built one: Visio Viewer, a Chrome extension that renders Visio files directly in your browser. [&#8230;]</p>
<p>The post <a href="https://www.danielnylander.se/2026/03/01/visio-viewer-a-chrome-extension-that-opens-vsdx-files-no-visio-required/">Visio Viewer: A Chrome Extension That Opens .vsdx Files — No Visio Required</a> first appeared on <a href="https://www.danielnylander.se">Daniel Nylander.se</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Ever received a <code>.vsdx</code> file and had no way to open it? Microsoft Visio is expensive, Windows-only, and most online converters want you to upload your diagrams to some random server. There had to be a better way.</p>
<p>So I built one: <strong>Visio Viewer</strong>, a Chrome extension that renders Visio files directly in your browser. No cloud. No uploads. No Visio license. Everything runs locally.</p>
<h2>What It Does</h2>
<p>Drop a <code>.vsdx</code> file onto Chrome (or use the file picker), and you get a clean SVG rendering of your diagram. The viewer supports:</p>
<ul>
<li><strong>Multi-page navigation</strong> — browse all pages in a Visio document</li>
<li><strong>Zoom &amp; pan</strong> — scroll to zoom, drag to pan, fit-to-page button</li>
<li><strong>Dark mode</strong> — because of course</li>
<li><strong>URL interception</strong> — click a link to a <code>.vsdx</code> file and it opens in the viewer automatically</li>
<li><strong>Open from URL</strong> — paste a URL to a remote <code>.vsdx</code> file</li>
</ul>
<figure class="wp-block-image size-large"><img data-recalc-dims="1" fetchpriority="high" decoding="async" width="1279" height="660" data-attachment-id="1862" data-permalink="https://www.danielnylander.se/visio-pondzod/" data-orig-file="https://i0.wp.com/www.danielnylander.se/wp-content/visio-pondzod.png?fit=1279%2C660&amp;ssl=1" data-orig-size="1279,660" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="visio-pondzod" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/www.danielnylander.se/wp-content/visio-pondzod.png?fit=300%2C155&amp;ssl=1" data-large-file="https://i0.wp.com/www.danielnylander.se/wp-content/visio-pondzod.png?fit=800%2C413&amp;ssl=1" src="https://i0.wp.com/www.danielnylander.se/wp-content/visio-pondzod.png?resize=1279%2C660&#038;ssl=1" alt="Network diagram with hundreds of nodes rendered in Visio Viewer" class="wp-image-1862" srcset="https://i0.wp.com/www.danielnylander.se/wp-content/visio-pondzod.png?w=1279&amp;ssl=1 1279w, https://i0.wp.com/www.danielnylander.se/wp-content/visio-pondzod.png?resize=300%2C155&amp;ssl=1 300w, https://i0.wp.com/www.danielnylander.se/wp-content/visio-pondzod.png?resize=800%2C413&amp;ssl=1 800w, https://i0.wp.com/www.danielnylander.se/wp-content/visio-pondzod.png?resize=768%2C396&amp;ssl=1 768w" sizes="(max-width: 1000px) 100vw, 1000px" /><figcaption>A large network overview diagram — zoomed out to 23%, all rendered client-side</figcaption></figure>
<figure class="wp-block-image size-large"><img data-recalc-dims="1" decoding="async" width="1279" height="660" data-attachment-id="1863" data-permalink="https://www.danielnylander.se/visio-bpmn/" data-orig-file="https://i0.wp.com/www.danielnylander.se/wp-content/visio-bpmn.png?fit=1279%2C660&amp;ssl=1" data-orig-size="1279,660" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="visio-bpmn" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/www.danielnylander.se/wp-content/visio-bpmn.png?fit=300%2C155&amp;ssl=1" data-large-file="https://i0.wp.com/www.danielnylander.se/wp-content/visio-bpmn.png?fit=800%2C413&amp;ssl=1" src="https://i0.wp.com/www.danielnylander.se/wp-content/visio-bpmn.png?resize=1279%2C660&#038;ssl=1" alt="BPMN diagram rendered in Visio Viewer" class="wp-image-1863" srcset="https://i0.wp.com/www.danielnylander.se/wp-content/visio-bpmn.png?w=1279&amp;ssl=1 1279w, https://i0.wp.com/www.danielnylander.se/wp-content/visio-bpmn.png?resize=300%2C155&amp;ssl=1 300w, https://i0.wp.com/www.danielnylander.se/wp-content/visio-bpmn.png?resize=800%2C413&amp;ssl=1 800w, https://i0.wp.com/www.danielnylander.se/wp-content/visio-bpmn.png?resize=768%2C396&amp;ssl=1 768w" sizes="(max-width: 1000px) 100vw, 1000px" /><figcaption>A BPMN sample diagram with colored shapes and connectors</figcaption></figure>
<figure class="wp-block-image size-large"><img data-recalc-dims="1" decoding="async" width="1279" height="660" data-attachment-id="1864" data-permalink="https://www.danielnylander.se/visio-mikrotik/" data-orig-file="https://i0.wp.com/www.danielnylander.se/wp-content/visio-mikrotik.png?fit=1279%2C660&amp;ssl=1" data-orig-size="1279,660" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="visio-mikrotik" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/www.danielnylander.se/wp-content/visio-mikrotik.png?fit=300%2C155&amp;ssl=1" data-large-file="https://i0.wp.com/www.danielnylander.se/wp-content/visio-mikrotik.png?fit=800%2C413&amp;ssl=1" src="https://i0.wp.com/www.danielnylander.se/wp-content/visio-mikrotik.png?resize=1279%2C660&#038;ssl=1" alt="MikroTik switch diagram rendered in Visio Viewer" class="wp-image-1864" srcset="https://i0.wp.com/www.danielnylander.se/wp-content/visio-mikrotik.png?w=1279&amp;ssl=1 1279w, https://i0.wp.com/www.danielnylander.se/wp-content/visio-mikrotik.png?resize=300%2C155&amp;ssl=1 300w, https://i0.wp.com/www.danielnylander.se/wp-content/visio-mikrotik.png?resize=800%2C413&amp;ssl=1 800w, https://i0.wp.com/www.danielnylander.se/wp-content/visio-mikrotik.png?resize=768%2C396&amp;ssl=1 768w" sizes="(max-width: 1000px) 100vw, 1000px" /><figcaption>A detailed MikroTik CRS312 switch stencil — rendered as crisp SVG</figcaption></figure>
<h2>How It Works</h2>
<p>Under the hood, the extension uses <a href="https://www.danielnylander.se/2026/02/28/libvisio-vs-libvisio-ng-why-we-built-a-pure-python-visio-parser/">libvisio-ng</a> — a pure Python Visio parser I built — running inside <a href="https://pyodide.org">Pyodide</a> (a full CPython compiled to WebAssembly). The entire pipeline runs in a sandboxed iframe:</p>
<ol>
<li>The extension intercepts <code>.vsdx</code> files (via drag &amp; drop, file picker, or URL)</li>
<li>The file is passed to libvisio-ng running in Pyodide (Python in WASM)</li>
<li>libvisio-ng parses the OPC/XML structure and produces SVG output</li>
<li>The SVG is rendered in the viewer with zoom/pan controls</li>
</ol>
<p><strong>All processing happens locally in your browser.</strong> No data leaves your machine. It works completely offline once installed.</p>
<figure class="wp-block-image size-large"><img data-recalc-dims="1" loading="lazy" decoding="async" width="1279" height="660" data-attachment-id="1865" data-permalink="https://www.danielnylander.se/visio-final/" data-orig-file="https://i0.wp.com/www.danielnylander.se/wp-content/visio-final.png?fit=1279%2C660&amp;ssl=1" data-orig-size="1279,660" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="visio-final" data-image-description="" data-image-caption="" data-medium-file="https://i0.wp.com/www.danielnylander.se/wp-content/visio-final.png?fit=300%2C155&amp;ssl=1" data-large-file="https://i0.wp.com/www.danielnylander.se/wp-content/visio-final.png?fit=800%2C413&amp;ssl=1" src="https://i0.wp.com/www.danielnylander.se/wp-content/visio-final.png?resize=1279%2C660&#038;ssl=1" alt="Simple Visio diagram showing Hello World" class="wp-image-1865" srcset="https://i0.wp.com/www.danielnylander.se/wp-content/visio-final.png?w=1279&amp;ssl=1 1279w, https://i0.wp.com/www.danielnylander.se/wp-content/visio-final.png?resize=300%2C155&amp;ssl=1 300w, https://i0.wp.com/www.danielnylander.se/wp-content/visio-final.png?resize=800%2C413&amp;ssl=1 800w, https://i0.wp.com/www.danielnylander.se/wp-content/visio-final.png?resize=768%2C396&amp;ssl=1 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /><figcaption>Even simple diagrams render cleanly</figcaption></figure>
<h2>Installation</h2>
<p>Version 1.2.0 is available now:</p>
<ul>
<li><strong>GitHub Release:</strong> <a href="https://github.com/yeager/visio-viewer-extension/releases/tag/v1.2.0">Download the .crx or load unpacked</a></li>
<li><strong>Chrome Web Store:</strong> Coming soon</li>
</ul>
<p>To install from GitHub: download the release, unzip, go to <code>chrome://extensions</code>, enable Developer mode, and click &#8221;Load unpacked&#8221;.</p>
<h2>Open Source</h2>
<p>The extension is open source under MIT/GPL. Contributions welcome.</p>
<ul>
<li><a href="https://github.com/yeager/visio-viewer-extension">GitHub Repository</a></li>
<li><a href="https://www.danielnylander.se/2026/02/28/libvisio-vs-libvisio-ng-why-we-built-a-pure-python-visio-parser/">libvisio-ng blog post</a> — the parser that powers it all</li>
</ul><p>The post <a href="https://www.danielnylander.se/2026/03/01/visio-viewer-a-chrome-extension-that-opens-vsdx-files-no-visio-required/">Visio Viewer: A Chrome Extension That Opens .vsdx Files — No Visio Required</a> first appeared on <a href="https://www.danielnylander.se">Daniel Nylander.se</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.danielnylander.se/2026/03/01/visio-viewer-a-chrome-extension-that-opens-vsdx-files-no-visio-required/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1867</post-id>	</item>
		<item>
		<title>Bättre svenska i espeak-ng</title>
		<link>https://www.danielnylander.se/2026/03/01/battre-svenska-i-espeak-ng/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=battre-svenska-i-espeak-ng</link>
					<comments>https://www.danielnylander.se/2026/03/01/battre-svenska-i-espeak-ng/#respond</comments>
		
		<dc:creator><![CDATA[Daniel Nylander]]></dc:creator>
		<pubDate>Sun, 01 Mar 2026 07:05:57 +0000</pubDate>
				<category><![CDATA[Teknik]]></category>
		<category><![CDATA[Tillgänglighet]]></category>
		<guid isPermaLink="false">https://www.danielnylander.se/2026/03/01/battre-svenska-i-espeak-ng/</guid>

					<description><![CDATA[<p>Jag har skickat en pull request till espeak-ng med stora förbättringar av det svenska uttalet. espeak-ng är den talsyntes som används av bland annat Orca (skärmläsaren i GNOME/Linux) och ligger till grund för i princip all TTS på Linux. Vad var fel? Svenska i espeak-ng har länge haft problem. Det mest uppenbara var att sje-ljudet [&#8230;]</p>
<p>The post <a href="https://www.danielnylander.se/2026/03/01/battre-svenska-i-espeak-ng/">Bättre svenska i espeak-ng</a> first appeared on <a href="https://www.danielnylander.se">Daniel Nylander.se</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Jag har skickat en <a href="https://github.com/espeak-ng/espeak-ng/pull/2364">pull request till espeak-ng</a> med stora förbättringar av det svenska uttalet. espeak-ng är den talsyntes som används av bland annat <strong>Orca</strong> (skärmläsaren i GNOME/Linux) och ligger till grund för i princip all TTS på Linux.</p>
<h2>Vad var fel?</h2>
<p>Svenska i espeak-ng har länge haft problem. Det mest uppenbara var att <strong>sje-ljudet</strong> (ɧ) — det karakteristiska svenska ljudet i ord som &quot;sjö&quot;, &quot;skjorta&quot; och &quot;stjärna&quot; — var felmappat till tj-ljud (ɕ). Det innebar att &quot;sju&quot; lät som &quot;tju&quot; och &quot;sjuk&quot; som &quot;tjuk&quot;. Inte direkt begripligt.</p>
<p>Dessutom saknades regler för vanliga svenska ljudkombinationer: <strong>dj</strong> (djur, djup), <strong>hj</strong> (hjärta, hjälm) och <strong>lj</strong> (ljus, ljud) uttalades bokstavligt istället för som /j/. Och suffixet <strong>-tion</strong> (station, funktion) fick helt fel uttal.</p>
<h2>Fas 1 — Grundläggande uttalsregler</h2>
<ul style="line-height:1.8;">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>sje-ljud:</strong> skj → /ɧ/ (var felaktigt /ɕ/)</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>-tion/-tions:</strong> korrekta regler för detta vanliga suffix</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>dj/hj/lj:</strong> nya regler för → /j/</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>230+ nya ord</strong> i ordlistan (nu totalt 899): veckodagar, månader, siffror, vanliga ord, förkortningar, ortnamn, tekniktermer</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>16 nya symboler:</strong> £, §, °, bråk, pilar, euro med mera</li>
</ul>
<h2>Fas 2 — Retroflexer <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h2>
<p>Retroflexerna är nu implementerade och mergade. Svenska retroflexer (rt → ʈ, rd → ɖ, rn → ɳ, rl → ɭ) fungerar korrekt — det som gör att &quot;barn&quot; uttalas med ɳ och &quot;gården&quot; med ɖ, precis som i naturligt tal.</p>
<h2>Fas 3–10 — Massiv expansion <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h2>
<p>Efter retroflexerna fortsatte arbetet i åtta ytterligare faser:</p>
<ul style="line-height:1.8;">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Fas 3–4: Vokalkorrigeringar</strong> — lång u (ʉː), bättre vokallängder, sje-ljud (ɧ) fixat genomgående</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Fas 5–6: Grammatik och prosodi</strong> — ”de/dem” → /dɔm/, ”det” → /deː/, fyra svenska intonationsmönster</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Fas 7–8: Egennamn och ortnamn</strong> — Göteborg, Trollhättan, Malmö, Karin, Andersson m.fl.</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Fas 9–10: IT-termer och lånord</strong> — browser, screenshot, wifi, offline, IT-säkerhet</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>1 197 ord</strong> i sv_list (från ~170 i originalet)</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>~50 nya uttalsregler</strong> i sv_rules</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Prosodijustering</strong> — bredare tonhöjdsvariation, naturligare vokallängder och förbättrad frågeintonation</li>
</ul>
<h2><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f50a.png" alt="🔊" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Lyssna — före och efter (fas 3–10)</h2>
<p>Dessa meningar visar förbättringarna från de senare faserna. Jämför systemets espeak-ng med vår förbättrade version:</p>
<div style="overflow-x:auto; margin:1.5em 0;">
<table style="width:100%; border-collapse:collapse; min-width:400px;">
<thead>
<tr style="background:#2c3e50; color:#fff;">
<th style="padding:10px 8px; border:1px solid #ddd; text-align:left; width:40%;">Mening</th>
<th style="padding:10px 8px; border:1px solid #ddd; text-align:center; width:45%;">Före</th>
<th style="padding:10px 8px; border:1px solid #ddd; text-align:center; width:45%;">Efter</th>
</tr>
</thead>
<tbody>
<tr style="background:#f9f9f9;">
<td style="padding:8px; border:1px solid #ddd;"><em>”De gick till Göteborg på onsdag för att handla köttbullar.”</em><br /><small style="color:#666;">de→/dɔm/, Göteborg, köttbullar</small></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_fore_5.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_efter_5_prosody-1.wav" type="audio/wav"/></audio></td>
</tr>
<tr>
<td style="padding:8px; border:1px solid #ddd;"><em>”Det är riktigt viktigt att barnen äter frukost varje dag.”</em><br /><small style="color:#666;">det→/deː/, riktigt, viktigt</small></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_fore_6.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_efter_6_prosody-1.wav" type="audio/wav"/></audio></td>
</tr>
<tr style="background:#f9f9f9;">
<td style="padding:8px; border:1px solid #ddd;"><em>”Karin Andersson bor i Trollhättan och jobbar med IT-säkerhet.”</em><br /><small style="color:#666;">Egennamn, ortnamn, IT-termer</small></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_fore_7.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_efter_7_prosody-1.wav" type="audio/wav"/></audio></td>
</tr>
<tr>
<td style="padding:8px; border:1px solid #ddd;"><em>”Vill du starta din browser och ladda ner appen?”</em><br /><small style="color:#666;">Frågeintonation, lånord</small></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_fore_8.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_efter_8_prosody-1.wav" type="audio/wav"/></audio></td>
</tr>
</tbody>
</table>
</div>
<h2>Fas 11–13 — Sammansatta ord, lånord och prosodi <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></h2>
<ul style="line-height:1.8;">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Fas 11: Sammansatta ord</strong> — 37 vanliga sammansättningar: köttbullar, busshållplats, parkeringsplats, vardagsrum, mataffär m.fl.</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Fas 12: Lånord</strong> — 11 vanliga lånord: restaurang, garage, parfym, journalist m.fl.</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Fas 13: Prosodiregler och suffix</strong> — 18 suffix-uttal och ordinaltal (13:e–31:a), vokalpar (glas/glass, ful/full)</li>
</ul>
<h2><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f50a.png" alt="🔊" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Nya ljudexempel (fas 13)</h2>
<p>Lyssna på den förbättrade svenska rösten med espeak-ng:</p>
<div style="overflow-x:auto; margin:1.5em 0;">
<table style="width:100%; border-collapse:collapse; min-width:500px;">
<thead>
<tr style="background:#2c3e50; color:#fff;">
<th style="padding:10px 8px; border:1px solid #ddd; text-align:left; width:45%;">Text</th>
<th style="padding:10px 8px; border:1px solid #ddd; text-align:center; width:45%;">espeak-ng (vår)</th>
</tr>
</thead>
<tbody>
<tr style="background:#f9f9f9;">
<td style="padding:8px; border:1px solid #ddd;"><em>&#8221;Hej, jag heter Alma och jag pratar svenska.&#8221;</em></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/intro.mp3" type="audio/mpeg"/></audio></td>
</tr>
<tr>
<td style="padding:8px; border:1px solid #ddd;"><em>&#8221;Sjuksköterskan skötte sjuttiosju sjösjuka sjömän.&#8221;</em><br /><small style="color:#666;">sje-ljud (ɧ)</small></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/sje-ljud.mp3" type="audio/mpeg"/></audio></td>
</tr>
<tr style="background:#f9f9f9;">
<td style="padding:8px; border:1px solid #ddd;"><em>&#8221;Kött och potatis med lingonsylt är en klassisk svensk rätt.&#8221;</em><br /><small style="color:#666;">sammansatta ord</small></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/mat.mp3" type="audio/mpeg"/></audio></td>
</tr>
<tr>
<td style="padding:8px; border:1px solid #ddd;"><em>&#8221;Stockholm är Sveriges huvudstad med över en miljon invånare.&#8221;</em></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/stockholm.mp3" type="audio/mpeg"/></audio></td>
</tr>
<tr style="background:#f9f9f9;">
<td style="padding:8px; border:1px solid #ddd;"><em>&#8221;Flygande bäckasiner söka hwila på mjuka tuvor.&#8221;</em><br /><small style="color:#666;">pangram</small></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/pangram.mp3" type="audio/mpeg"/></audio></td>
</tr>
<tr>
<td style="padding:8px; border:1px solid #ddd;"><em>&#8221;Trettiotre trista tråkiga trollungar trampade trettiofyra trappsteg.&#8221;</em><br /><small style="color:#666;">tungvrickare</small></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/tungvrickare.mp3" type="audio/mpeg"/></audio></td>
</tr>
<tr style="background:#f9f9f9;">
<td style="padding:8px; border:1px solid #ddd;"><em>&#8221;God morgon! Hur mår du idag?&#8221;</em><br /><small style="color:#666;">frågeintonation</small></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/halsning.mp3" type="audio/mpeg"/></audio></td>
</tr>
<tr>
<td style="padding:8px; border:1px solid #ddd;"><em>&#8221;Barnen leker i parken medan solen skiner.&#8221;</em></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/barn.mp3" type="audio/mpeg"/></audio></td>
</tr>
</tbody>
</table>
</div>
<h2>Statistik</h2>
<ul style="line-height:1.8;">
<li><strong>1 197 ord</strong> i sv_list (från ~170 i originalet)</li>
<li><strong>Retroflexer:</strong> ɖ, ɳ, ɭ, ʈ — alla implementerade</li>
<li><strong>4 svenska intonationsmönster</strong> (deklarativ, fråga, uppräkning, emfas)</li>
<li><strong>Fonemfixar:</strong> sje-ljud ɧ korrigerat, lång u (ʉː) fixat</li>
<li><strong>”de/dem”</strong> → /dɔm/, <strong>”det”</strong> → /deː/</li>
<li><strong>~50 nya uttalsregler</strong> i sv_rules</li>
<li><strong>42 vokalpar</strong> med korrekt kvantitetsdistinktion (glas/glass, ful/full)</li>
<li><strong>Ordinaltal</strong> 13:e–31:a med korrekt uttal</li>
<li><strong>13 faser</strong> av förbättringar</li>
</ul>
<h2>Status</h2>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Alla CI-tester gröna.</strong> Pull requesten väntar nu på review från espeak-ng-teamet. Detta är den största förbättringen av det svenska uttalet i espeak-ng:s historia — ordlistan har gått från ~170 till 1 197 ord i 13 faser, med helt nya uttalsregler, retroflexer, prosodijusteringar, sammansatta ord, lånord och korrekt sje-ljud.</p>
<h2>Varför det spelar roll</h2>
<p>espeak-ng är inte den snyggaste talsyntesen, men den är <strong>den viktigaste</strong>. Den är fri, öppen källkod, och den enda TTS som alla Linux-användare har tillgång till utan extra kostnad eller molntjänster. För <strong>synskadade</strong> användare som förlitar sig på Orca är detta deras röst. Att den rösten ska uttala svenska korrekt borde vara en självklarhet.</p>
<p style="margin-top:2em;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f449.png" alt="👉" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <a href="https://github.com/espeak-ng/espeak-ng/pull/2364">Pull request #2364 på GitHub</a></p><p>The post <a href="https://www.danielnylander.se/2026/03/01/battre-svenska-i-espeak-ng/">Bättre svenska i espeak-ng</a> first appeared on <a href="https://www.danielnylander.se">Daniel Nylander.se</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.danielnylander.se/2026/03/01/battre-svenska-i-espeak-ng/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		<enclosure url="https://www.danielnylander.se/wp-content/espeak_fore_5.wav" length="158348" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_fore_6.wav" length="177794" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_fore_7.wav" length="181508" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_fore_8.wav" length="118094" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_efter_5_prosody-1.wav" length="102210" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_efter_6_prosody-1.wav" length="104256" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_efter_7_prosody-1.wav" length="113226" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_efter_8_prosody-1.wav" length="74854" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/intro.mp3" length="33479" type="audio/mpeg" />
<enclosure url="https://www.danielnylander.se/wp-content/sje-ljud.mp3" length="33897" type="audio/mpeg" />
<enclosure url="https://www.danielnylander.se/wp-content/mat.mp3" length="39331" type="audio/mpeg" />
<enclosure url="https://www.danielnylander.se/wp-content/stockholm.mp3" length="41421" type="audio/mpeg" />
<enclosure url="https://www.danielnylander.se/wp-content/pangram.mp3" length="33897" type="audio/mpeg" />
<enclosure url="https://www.danielnylander.se/wp-content/tungvrickare.mp3" length="53541" type="audio/mpeg" />
<enclosure url="https://www.danielnylander.se/wp-content/halsning.mp3" length="23448" type="audio/mpeg" />
<enclosure url="https://www.danielnylander.se/wp-content/barn.mp3" length="29300" type="audio/mpeg" />

		<post-id xmlns="com-wordpress:feed-additions:1">1773</post-id>	</item>
		<item>
		<title>libvisio-ng 0.6.0 och VSDView 0.5.0 — nu ännu längre före C++-versionen</title>
		<link>https://www.danielnylander.se/2026/03/01/libvisio-ng-0-6-0-och-vsdview-0-5-0-nu-annu-langre-fore-c-versionen/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=libvisio-ng-0-6-0-och-vsdview-0-5-0-nu-annu-langre-fore-c-versionen</link>
					<comments>https://www.danielnylander.se/2026/03/01/libvisio-ng-0-6-0-och-vsdview-0-5-0-nu-annu-langre-fore-c-versionen/#respond</comments>
		
		<dc:creator><![CDATA[Daniel Nylander]]></dc:creator>
		<pubDate>Sun, 01 Mar 2026 06:56:39 +0000</pubDate>
				<category><![CDATA[Teknik]]></category>
		<guid isPermaLink="false">https://www.danielnylander.se/2026/03/01/libvisio-ng-0-6-0-och-vsdview-0-5-0-nu-annu-langre-fore-c-versionen/</guid>

					<description><![CDATA[<p>Det har hänt en hel del sedan förra releasen. Både libvisio-ng och VSDView har fått rejäla uppgraderingar, och gapet till det gamla C++-baserade libvisio har bara ökat. libvisio-ng 0.6.0 Den här releasen handlar mycket om att hantera fler av Visios visuella funktioner korrekt — saker som det gamla C++-biblioteket aldrig implementerade. Nya funktioner: &#x2705; Rich [&#8230;]</p>
<p>The post <a href="https://www.danielnylander.se/2026/03/01/libvisio-ng-0-6-0-och-vsdview-0-5-0-nu-annu-langre-fore-c-versionen/">libvisio-ng 0.6.0 och VSDView 0.5.0 — nu ännu längre före C++-versionen</a> first appeared on <a href="https://www.danielnylander.se">Daniel Nylander.se</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Det har hänt en hel del sedan förra releasen. Både libvisio-ng och VSDView har fått rejäla uppgraderingar, och gapet till det gamla C++-baserade libvisio har bara ökat.</p>
<h2>libvisio-ng 0.6.0</h2>
<p>Den här releasen handlar mycket om att hantera fler av Visios visuella funktioner korrekt — saker som det gamla C++-biblioteket aldrig implementerade.</p>
<p><strong>Nya funktioner:</strong></p>
<ul style="line-height:1.8;">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Rich text</strong> — formaterad text i shapes renderas nu korrekt med fetstil, kursiv, teckenstorlek och färg</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Radiella gradienter</strong> — inte bara linjära längre, utan även radiella gradienter stöds nu fullt ut</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Bildinbäddning</strong> — inbäddade bilder (EMF, PNG, JPEG) i .vsdx-filer extraheras och renderas i SVG-output</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Type hints</strong> — hela kodbasen har fått type annotations, vilket gör det enklare att bidra och integrera</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Sphinx-dokumentation</strong> — ordentlig API-dokumentation genererad med Sphinx</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>CI-pipeline</strong> — automatiserade tester och kvalitetskontroll vid varje commit</li>
</ul>
<p>Testsviten har vuxit från 96 till 102 tester. Varje test validerar att en specifik Visio-fil konverteras korrekt — det är ingen leksak.</p>
<p><strong>libvisio-ng finns nu på PyPI:</strong></p>
<pre style="background:#f5f5f5; padding:12px 16px; border-radius:6px; border:1px solid #e0e0e0; overflow-x:auto;"><code>pip install libvisio-ng</code></pre>
<p>Ren Python. Inga C++-beroenden. Inga systembibliotek att krångla med. Det bara funkar.</p>
<h2>libvisio-rs — Rust-porten</h2>
<p>Det som tidigare var &#8221;nästa steg&#8221; är nu verklighet. <strong>libvisio-rs v0.1.1</strong> är en fullständig Rust-port av libvisio-ng med C ABI via cbindgen-genererade headers — redo att droppa in som ersättare för C++ libvisio i LibreOffice och Inkscape.</p>
<ul style="line-height:1.8;">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>C ABI</strong> — cbindgen-genererade headers gör det möjligt att länka direkt från C/C++-projekt</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>PyO3 Python-bindings</strong> — samma API som libvisio-ng, men med Rust-prestanda</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Inkscape-extension</strong> — inskickat som <a href="https://gitlab.com/inkscape/extensions/-/merge_requests/718">MR #718</a></li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>LibreOffice</strong> — enhancement proposal inskickat</li>
</ul>
<p>Installera via crates.io:</p>
<pre style="background:#f5f5f5; padding:12px 16px; border-radius:6px; border:1px solid #e0e0e0; overflow-x:auto;"><code>cargo add libvisio-rs</code></pre>
<p>Koden finns på <a href="https://github.com/yeager/libvisio-rs">github.com/yeager/libvisio-rs</a> och <a href="https://crates.io/crates/libvisio-rs">crates.io/crates/libvisio-rs</a>.</p>
<h3>Jämförelse: libvisio-ng/rs vs C++ libvisio</h3>
<p>Det här projektet startade för att C++-versionen av libvisio (som LibreOffice använder) hade stagnerat. Ingen aktiv utveckling sedan ~2018, bristfälligt stöd för teman, gradienter, skuggor och textformatering. Här är den fullständiga jämförelsen:</p>
<div style="overflow-x:auto; margin:1.5em 0;">
<table style="border-collapse:collapse; width:100%; min-width:500px;">
<thead>
<tr style="background:#2c3e50; color:#fff;">
<th style="padding:10px 12px; border:1px solid #ddd; text-align:left;">Funktion</th>
<th style="padding:10px 12px; border:1px solid #ddd; text-align:center;">C++ libvisio</th>
<th style="padding:10px 12px; border:1px solid #ddd; text-align:center;">libvisio-ng/rs</th>
</tr>
</thead>
<tbody>
<tr style="background:#f9f9f9;">
<td style="padding:8px 12px; border:1px solid #ddd;">.vsdx-stöd</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;">Grundläggande</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Fullt (teman, gradienter, skuggor)</td>
</tr>
<tr>
<td style="padding:8px 12px; border:1px solid #ddd;">.vsd-stöd (binärt)</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;">Bra</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Fullt (NURBS, splines, bilder, lager)</td>
</tr>
<tr style="background:#f9f9f9;">
<td style="padding:8px 12px; border:1px solid #ddd;">Temafärger</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr>
<td style="padding:8px 12px; border:1px solid #ddd;">Linjära gradienter</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;">Delvis</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr style="background:#f9f9f9;">
<td style="padding:8px 12px; border:1px solid #ddd;">Radiella gradienter</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr>
<td style="padding:8px 12px; border:1px solid #ddd;">Skuggor</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr style="background:#f9f9f9;">
<td style="padding:8px 12px; border:1px solid #ddd;">Skraffering/mönsterfyllning</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr>
<td style="padding:8px 12px; border:1px solid #ddd;">Rich text (blandade stilar)</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;">Delvis</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr style="background:#f9f9f9;">
<td style="padding:8px 12px; border:1px solid #ddd;">Bildinbäddning</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;">Delvis</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr>
<td style="padding:8px 12px; border:1px solid #ddd;">Konnektorer</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;">Grundläggande</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Full med routing</td>
</tr>
<tr style="background:#f9f9f9;">
<td style="padding:8px 12px; border:1px solid #ddd;">Master shape-arv</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;">Delvis</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Fullt</td>
</tr>
<tr>
<td style="padding:8px 12px; border:1px solid #ddd;">Hyperlänkar</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr style="background:#f9f9f9;">
<td style="padding:8px 12px; border:1px solid #ddd;">Rundade rektanglar</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr>
<td style="padding:8px 12px; border:1px solid #ddd;">Linjemönster (streckade m.m.)</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;">Grundläggande</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Fullt</td>
</tr>
<tr style="background:#f9f9f9;">
<td style="padding:8px 12px; border:1px solid #ddd;">Fyllnadsmönster</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr>
<td style="padding:8px 12px; border:1px solid #ddd;">Pilmarkörer</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;">Delvis</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr style="background:#f9f9f9;">
<td style="padding:8px 12px; border:1px solid #ddd;">Tester</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;">Begränsat</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;">102</td>
</tr>
<tr>
<td style="padding:8px 12px; border:1px solid #ddd;">Språk</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;">C++</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;">Python + Rust + C ABI</td>
</tr>
<tr style="background:#f9f9f9;">
<td style="padding:8px 12px; border:1px solid #ddd;">Aktiv utveckling</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> (senast ~2018)</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr>
<td style="padding:8px 12px; border:1px solid #ddd;">PyPI</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> libvisio-ng</td>
</tr>
<tr style="background:#f9f9f9;">
<td style="padding:8px 12px; border:1px solid #ddd;">crates.io</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> libvisio-rs</td>
</tr>
<tr>
<td style="padding:8px 12px; border:1px solid #ddd;">Homebrew</td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="padding:8px 12px; border:1px solid #ddd; text-align:center;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> (via VSDView)</td>
</tr>
</tbody>
</table>
</div>
<h2>VSDView 0.5.0</h2>
<p>VSDView är den grafiska Visio-läsaren som bygger på libvisio-ng. Version 0.5.0 är en massiv uppgradering med 15 nya funktioner:</p>
<ul style="line-height:1.8;">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Zoom och panorering</strong> — scrolla och zooma fritt i diagrammet</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Sökfunktion</strong> — hitta shapes och text i dokumentet</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Shape-information</strong> — klicka på en shape för att se dess egenskaper</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Mätverktyg</strong> — mät avstånd direkt i diagrammet</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Export</strong> — spara som SVG, PNG eller PDF</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Lagerhantering</strong> — visa/dölj lager</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Minimap</strong> — överblick över hela dokumentet</li>
<li>…och mer</li>
</ul>
<p>Den stora förändringen under huven är att VSDView nu <strong>helt har ersatt C++ libvisio med libvisio-ng</strong>. Tidigare krävdes <code style="background:#f5f5f5; padding:2px 6px; border-radius:3px;">libvisio-tools</code> som systempaket — nu är allt inbyggt. 4000 rader gammal parser-kod ersattes med en 30-raders wrapper mot libvisio-ng. Resultatet: bättre rendering, enklare installation, och stöd för allt som libvisio-ng klarar.</p>
<p>Det finns också en <strong>Tauri-baserad nativapp (v0.2.0)</strong> med Alma TTS-integration.</p>
<h3><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4e6.png" alt="📦" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Installation</h3>
<ul style="line-height:1.8;">
<li><strong>macOS:</strong> <code style="background:#f5f5f5; padding:2px 6px; border-radius:3px;">brew install yeager/tap/vsdview</code></li>
<li><strong>Windows:</strong> Ladda ner från <a href="https://github.com/yeager/vsdview/releases/tag/v0.5.0">GitHub Releases</a></li>
<li><strong>Linux:</strong> .deb och .rpm i våra repos, eller <code style="background:#f5f5f5; padding:2px 6px; border-radius:3px;">pip install vsdview</code></li>
<li><strong>PyPI:</strong> <code style="background:#f5f5f5; padding:2px 6px; border-radius:3px;">pip install vsdview</code></li>
</ul>
<h2>Integration i ekosystemet</h2>
<p>Målet är att ersätta det ounderhållna C++ libvisio över hela open source-ekosystemet:</p>
<ul style="line-height:1.8;">
<li><strong>Inkscape:</strong> Extension inskickat som <a href="https://gitlab.com/inkscape/extensions/-/merge_requests/718">MR #718</a> — öppnar .vsd/.vsdx direkt i Inkscape via libvisio-ng</li>
<li><strong>LibreOffice:</strong> Enhancement proposal inskickat för att ersätta C++ libvisio med libvisio-rs</li>
</ul>
<p>Med libvisio-rs C ABI och cbindgen-headers kan projektet fungera som drop-in-ersättare för det gamla biblioteket. Python-versionen (libvisio-ng) driver redan VSDView och Inkscape-extensionen, medan Rust-versionen (libvisio-rs) riktar sig mot LibreOffice och andra C/C++-projekt.</p>
<h2>Länkar</h2>
<ul style="line-height:1.8;">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4e6.png" alt="📦" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>libvisio-ng:</strong> <a href="https://github.com/yeager/libvisio-ng">GitHub</a> · <a href="https://pypi.org/project/libvisio-ng/">PyPI</a></li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f980.png" alt="🦀" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>libvisio-rs:</strong> <a href="https://github.com/yeager/libvisio-rs">GitHub</a> · <a href="https://crates.io/crates/libvisio-rs">crates.io</a></li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f5a5.png" alt="🖥" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>VSDView:</strong> <a href="https://github.com/yeager/vsdview">GitHub</a></li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f917.png" alt="🤗" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>HuggingFace:</strong> <a href="https://huggingface.co/yeagersthlm">huggingface.co/yeagersthlm</a></li>
</ul>
<p style="margin-top:1em; color:#666;"><em>libvisio-ng, libvisio-rs och VSDView är öppen källkod under GPL-3.0.</em></p><p>The post <a href="https://www.danielnylander.se/2026/03/01/libvisio-ng-0-6-0-och-vsdview-0-5-0-nu-annu-langre-fore-c-versionen/">libvisio-ng 0.6.0 och VSDView 0.5.0 — nu ännu längre före C++-versionen</a> first appeared on <a href="https://www.danielnylander.se">Daniel Nylander.se</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.danielnylander.se/2026/03/01/libvisio-ng-0-6-0-och-vsdview-0-5-0-nu-annu-langre-fore-c-versionen/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1771</post-id>	</item>
		<item>
		<title>Alma — en svensk TTS-röst för barn med NPF</title>
		<link>https://www.danielnylander.se/2026/03/01/alma-en-svensk-tts-rost-for-barn-med-npf/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=alma-en-svensk-tts-rost-for-barn-med-npf</link>
					<comments>https://www.danielnylander.se/2026/03/01/alma-en-svensk-tts-rost-for-barn-med-npf/#respond</comments>
		
		<dc:creator><![CDATA[Daniel Nylander]]></dc:creator>
		<pubDate>Sun, 01 Mar 2026 05:46:12 +0000</pubDate>
				<category><![CDATA[Teknik]]></category>
		<category><![CDATA[Tillgänglighet]]></category>
		<guid isPermaLink="false">https://www.danielnylander.se/2026/03/01/alma-en-svensk-tts-rost-for-barn-med-npf/</guid>

					<description><![CDATA[<p>Jag har tränat en egen svensk TTS-röst med Piper TTS. Hon heter Alma, uppkallad efter min dotter, och är tänkt att användas i appar riktade till barn med NPF (neuropsykiatriska funktionsnedsättningar). Bakgrund Barnen i vår familj har alla olika varianter av autism, ADHD och språkstörning. De appar jag bygger åt dem (autismappar.se) behöver talstöd — [&#8230;]</p>
<p>The post <a href="https://www.danielnylander.se/2026/03/01/alma-en-svensk-tts-rost-for-barn-med-npf/">Alma — en svensk TTS-röst för barn med NPF</a> first appeared on <a href="https://www.danielnylander.se">Daniel Nylander.se</a>.</p>]]></description>
										<content:encoded><![CDATA[<p><script>function playWS(t){window.speechSynthesis.cancel();var u=new SpeechSynthesisUtterance(t);u.lang="sv-SE";u.rate=0.9;window.speechSynthesis.speak(u);}</script></p>
<p>Jag har tränat en egen svensk TTS-röst med <a href="https://github.com/rhasspy/piper">Piper TTS</a>. Hon heter Alma, uppkallad efter min dotter, och är tänkt att användas i appar riktade till barn med NPF (neuropsykiatriska funktionsnedsättningar).</p>
<h2>Bakgrund</h2>
<p>Barnen i vår familj har alla olika varianter av autism, ADHD och språkstörning. De appar jag bygger åt dem (<a href="https://autismappar.se">autismappar.se</a>) behöver talstöd — men de befintliga svenska TTS-rösterna låter antingen robotaktiga eller är helt enkelt inte anpassade för barn. Jag ville ha en röst som känns varm, tydlig och trygg.</p>
<h2>Tekniken</h2>
<p>Alma är finskiktad (finetunad) ovanpå <a href="https://huggingface.co/KBLab">KBLabs</a> svenska VITS-modell med hjälp av Piper TTS träningsramverk. Träningen kördes på en NVIDIA RTX 4080 i ungefär 5500 epoker — det tog några dagar, men resultatet blev bra.</p>
<p>Piper är ett lätt, snabbt och helt lokalt TTS-system. Ingen molntjänst behövs. Det körs direkt på enheten, vilket är viktigt för integritet och svarstid — speciellt i appar för barn.</p>
<h2><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Före och efter — röstjämförelse</h2>
<p>Här kan du höra skillnaden mellan de olika rösterna och våra förbättringar. Vi jämför fyra varianter: den omodifierade <strong>espeak-ng</strong> (systemets standardröst), vår <strong>förbättrade espeak-ng</strong> med retroflexer och bättre uttalsregler, <strong>Piper standard</strong> (sv_SE-nst-medium) och slutligen <strong>Alma</strong> — vår egna finjusterade röst med lånordsfix.</p>
<p>Lyssna särskilt på hur retroflexerna (rd, rn, rt) och engelska lånord uttalas.</p>
<div style="overflow-x:auto; margin:1.5em 0;">
<table style="width:100%; border-collapse:collapse; min-width:600px;">
<thead>
<tr style="background:#2c3e50; color:#fff;">
<th style="padding:8px 6px; border:1px solid #ddd; text-align:left; width:24%;">Mening</th>
<th style="padding:8px 6px; border:1px solid #ddd; text-align:center; width:15%;">espeak (före)</th>
<th style="padding:8px 6px; border:1px solid #ddd; text-align:center; width:15%;">espeak (efter)</th>
<th style="padding:8px 6px; border:1px solid #ddd; text-align:center; width:15%;">Piper std</th>
<th style="padding:8px 6px; border:1px solid #ddd; text-align:center; width:15%;">Alma</th>
<th style="padding:8px 6px; border:1px solid #ddd; text-align:center; width:16%;">Web Speech</th>
</tr>
</thead>
<tbody>
<tr style="background:#f9f9f9;">
<td style="padding:8px; border:1px solid #ddd;"><em>&#8221;Hej, jag heter Alma och jag ska hjälpa dig idag.&#8221;</em></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_fore_1-1.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_efter_1_prosody.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/piper_nst_1.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/alma_1.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><button onclick="playWS('Hej, jag heter Alma och jag ska hjälpa dig idag.')" style="padding:6px 12px;border-radius:8px;border:2px solid #3498db;background:#ecf0f1;cursor:pointer;font-size:0.85em;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/25b6.png" alt="▶" class="wp-smiley" style="height: 1em; max-height: 1em;" /></button></td>
</tr>
<tr>
<td style="padding:8px; border:1px solid #ddd;"><em>&#8221;Barnen lekte i gården hela lördagen.&#8221;</em><br /><small style="color:#666;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Retroflexer: barn→bɑːɳ, gården→goːɖen, lördagen→løːɖɑːgen</small></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_fore_2-1.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_efter_2_prosody.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/piper_nst_2.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/alma_2.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><button onclick="playWS('Barnen lekte i gården hela lördagen.')" style="padding:6px 12px;border-radius:8px;border:2px solid #3498db;background:#ecf0f1;cursor:pointer;font-size:0.85em;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/25b6.png" alt="▶" class="wp-smiley" style="height: 1em; max-height: 1em;" /></button></td>
</tr>
<tr style="background:#f9f9f9;">
<td style="padding:8px; border:1px solid #ddd;"><em>&#8221;Alla appar fungerar offline utan wifi.&#8221;</em><br /><small style="color:#666;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Lånord: offline→åfflajn, wifi→wajfaj</small></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_fore_3-1.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_efter_3_prosody.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/piper_nst_3.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/alma_3.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><button onclick="playWS('Alla appar fungerar offline utan wifi.')" style="padding:6px 12px;border-radius:8px;border:2px solid #3498db;background:#ecf0f1;cursor:pointer;font-size:0.85em;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/25b6.png" alt="▶" class="wp-smiley" style="height: 1em; max-height: 1em;" /></button></td>
</tr>
<tr>
<td style="padding:8px; border:1px solid #ddd;"><em>&#8221;Kan du peka på den röda bollen?&#8221;</em><br /><small style="color:#666;">Enkel barnvänlig mening</small></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_fore_4-1.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_efter_4_prosody.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/piper_nst_4.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/alma_4.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><button onclick="playWS('Kan du peka på den röda bollen?')" style="padding:6px 12px;border-radius:8px;border:2px solid #3498db;background:#ecf0f1;cursor:pointer;font-size:0.85em;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/25b6.png" alt="▶" class="wp-smiley" style="height: 1em; max-height: 1em;" /></button></td>
</tr>
<tr style="background:#f9f9f9;">
<td style="padding:8px; border:1px solid #ddd;" colspan="5"><strong style="color:#2c3e50;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Nya exempelmeningar — visar fas 3–10</strong></td>
</tr>
<tr>
<td style="padding:8px; border:1px solid #ddd;"><em>&#8221;De gick till Göteborg på onsdag för att handla köttbullar.&#8221;</em><br /><small style="color:#666;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> de→/dɔm/, Göteborg, onsdag, köttbullar</small></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_fore_5.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_efter_5_prosody.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/piper_nst_5.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/alma_5.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><button onclick="playWS('De gick till Göteborg på onsdag för att handla köttbullar.')" style="padding:6px 12px;border-radius:8px;border:2px solid #3498db;background:#ecf0f1;cursor:pointer;font-size:0.85em;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/25b6.png" alt="▶" class="wp-smiley" style="height: 1em; max-height: 1em;" /></button></td>
</tr>
<tr style="background:#f9f9f9;">
<td style="padding:8px; border:1px solid #ddd;"><em>&#8221;Det är riktigt viktigt att barnen äter frukost varje dag.&#8221;</em><br /><small style="color:#666;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> det→/deː/, riktigt, viktigt</small></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_fore_6.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_efter_6_prosody.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/piper_nst_6.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/alma_6.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><button onclick="playWS('Det är riktigt viktigt att barnen äter frukost varje dag.')" style="padding:6px 12px;border-radius:8px;border:2px solid #3498db;background:#ecf0f1;cursor:pointer;font-size:0.85em;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/25b6.png" alt="▶" class="wp-smiley" style="height: 1em; max-height: 1em;" /></button></td>
</tr>
<tr>
<td style="padding:8px; border:1px solid #ddd;"><em>&#8221;Karin Andersson bor i Trollhättan och jobbar med IT-säkerhet.&#8221;</em><br /><small style="color:#666;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Egennamn, ortnamn, IT-termer</small></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_fore_7.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_efter_7_prosody.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/piper_nst_7.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/alma_7.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><button onclick="playWS('Karin Andersson bor i Trollhättan och jobbar med IT-säkerhet.')" style="padding:6px 12px;border-radius:8px;border:2px solid #3498db;background:#ecf0f1;cursor:pointer;font-size:0.85em;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/25b6.png" alt="▶" class="wp-smiley" style="height: 1em; max-height: 1em;" /></button></td>
</tr>
<tr style="background:#f9f9f9;">
<td style="padding:8px; border:1px solid #ddd;"><em>&#8221;Vill du starta din browser och ladda ner appen?&#8221;</em><br /><small style="color:#666;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Frågeintonation, lånord (browser, appen)</small></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_fore_8.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/espeak_efter_8_prosody.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/piper_nst_8.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><audio controls preload="none" style="width:140px; height:32px;"><source src="https://www.danielnylander.se/wp-content/alma_8.wav" type="audio/wav"/></audio></td>
<td style="padding:8px; border:1px solid #ddd; text-align:center;"><button onclick="playWS('Vill du starta din browser och ladda ner appen?')" style="padding:6px 12px;border-radius:8px;border:2px solid #3498db;background:#ecf0f1;cursor:pointer;font-size:0.85em;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/25b6.png" alt="▶" class="wp-smiley" style="height: 1em; max-height: 1em;" /></button></td>
</tr>
</tbody>
</table>
</div>
<h3>Vad hör du?</h3>
<ul style="line-height:1.8;">
<li><strong>espeak-ng (före):</strong> Systemets standardröst — robotaktig och med fel uttal av retroflexer. &#8221;Barnen&#8221; uttalas med separata r+n istället för retroflex ɳ.</li>
<li><strong>espeak-ng (efter):</strong> Vår <a href="https://github.com/espeak-ng/espeak-ng/pull/2364">PR #2364</a> — retroflexer (ɳ, ɖ, ʈ) fungerar nu korrekt. Hör skillnaden i &#8221;barnen&#8221;, &#8221;gården&#8221; och &#8221;lördagen&#8221;.</li>
<li><strong>Piper standard:</strong> Neural röst (sv_SE-nst-medium) — mycket naturligare, men uttalar engelska lånord bokstavligt (&#8221;offline&#8221; som det stavas).</li>
<li><strong>Alma:</strong> Vår finjusterade röst med fonetisk förbehandling — lånord uttalas korrekt (&#8221;åfflajn&#8221;, &#8221;wajfaj&#8221;) och rösten är optimerad för barn.</li>
</ul>
<h2>Jämförelse: standardröst vs Alma</h2>
<p>Här nedan kan du lyssna på samma meningar upplästa av standardrösten (sv_SE-nst-medium) och Alma. Meningarna innehåller engelska lånord som <em>offline</em>, <em>wifi</em>, <em>screenshot</em> och <em>browser</em> — ord som ofta förekommer i apparna och som nu uttalas korrekt tack vare fonetisk förbehandling.</p>
<h3>&#8221;Alla appar fungerar offline, utan wifi eller internet.&#8221;</h3>
<p><strong>Standardröst:</strong></p>
<p><audio controls preload="none" style="width:100%; max-width:400px; height:36px;"><source src="https://www.danielnylander.se/wp-content/short1-default.wav" type="audio/wav"/></audio></p>
<p><strong>Alma:</strong></p>
<p><audio controls preload="none" style="width:100%; max-width:400px; height:36px;"><source src="https://www.danielnylander.se/wp-content/short1-alma.wav" type="audio/wav"/></audio></p>
<h3>&#8221;Du kan ladda ner uppdateringar och ta en screenshot av dina resultat.&#8221;</h3>
<p><strong>Standardröst:</strong></p>
<p><audio controls preload="none" style="width:100%; max-width:400px; height:36px;"><source src="https://www.danielnylander.se/wp-content/short2-default.wav" type="audio/wav"/></audio></p>
<p><strong>Alma:</strong></p>
<p><audio controls preload="none" style="width:100%; max-width:400px; height:36px;"><source src="https://www.danielnylander.se/wp-content/short2-alma.wav" type="audio/wav"/></audio></p>
<h3>&#8221;Öppna din browser och klicka på länken i ditt email.&#8221;</h3>
<p><strong>Standardröst:</strong></p>
<p><audio controls preload="none" style="width:100%; max-width:400px; height:36px;"><source src="https://www.danielnylander.se/wp-content/short3-default.wav" type="audio/wav"/></audio></p>
<p><strong>Alma:</strong></p>
<p><audio controls preload="none" style="width:100%; max-width:400px; height:36px;"><source src="https://www.danielnylander.se/wp-content/short3-alma.wav" type="audio/wav"/></audio></p>
<h2>Nästa steg</h2>
<p>Alma-rösten är redo att integreras i apparna på <a href="https://autismappar.se">autismappar.se</a>. Planen är att använda henne som standardröst i de appar som riktar sig till yngre barn. Modellen exporteras som ONNX och kan köras helt offline — inget moln, ingen latens, ingen dataläckage.</p>
<h2>Längre exempel</h2>
<p>Här är ett längre stycke med blandning av vanlig svenska och engelska lånord. Alma pratar lugnt och tydligt, i ett tempo som passar yngre barn.</p>
<p><strong>Standardröst:</strong></p>
<p><audio controls preload="none" style="width:100%; max-width:400px; height:36px;"><source src="https://www.danielnylander.se/wp-content/long-default.wav" type="audio/wav"/></audio></p>
<p><strong>Alma:</strong></p>
<p><audio controls preload="none" style="width:100%; max-width:400px; height:36px;"><source src="https://www.danielnylander.se/wp-content/long-alma.wav" type="audio/wav"/></audio></p>
<h2>Uttalförbättringar</h2>
<p>Ett stort problem med svenska TTS-röster är engelska lånord. Ord som <em>offline</em>, <em>wifi</em>, <em>screenshot</em> och <em>email</em> uttalas bokstavligt — vilket låter helt fel. I barnens appar förekommer dessa ord överallt, så det behövde lösas.</p>
<h3>Fonetisk förbehandling</h3>
<p>Lösningen är en enkel men effektiv preprocessing-pipeline: innan texten skickas till Piper ersätts cirka 30 vanliga engelska lånord med svenska fonetiska stavningar. Till exempel:</p>
<ul style="line-height:1.8;">
<li><em>offline</em> → <em>åfflajn</em></li>
<li><em>wifi</em> → <em>wajfaj</em></li>
<li><em>screenshot</em> → <em>skriinsjått</em></li>
</ul>
<p>Samma pipeline funkar med både Piper och Web Speech API.</p>
<h3>espeak-ng: svenska uttalsregler</h3>
<p>Parallellt med den fonetiska kartläggningen har jag skickat in en <a href="https://github.com/espeak-ng/espeak-ng/pull/2364">pull request till espeak-ng</a> med förbättrade svenska uttalsregler. Bland annat:</p>
<ul style="line-height:1.8;">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Korrekta sje-ljud (sj, skj, stj, sch)</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Rätt hantering av <em>-tion</em>, <em>gn-</em>, <em>dj-</em>, <em>hj-</em>, <em>lj-</em></li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Över 899 ord i den svenska ordboken (10 faser av förbättringar)</li>
</ul>
<p>espeak-ng är den fonemiserare som Piper använder under huven, så bättre regler där ger bättre uttal i Alma direkt.</p>
<h2>Alma i GNOME Orca</h2>
<p>Alma fungerar nu som röst i <strong>GNOME:s skärmläsare Orca</strong> via <a href="https://project-spiel.org/">Spiel</a> — GNOME:s nya talramverk. Det här är stort: för första gången kan svenska blinda och synskadade Linux-användare få en naturlig, neural svensk röst i sin skärmläsare.</p>
<p>Spiel ersätter det gamla speech-dispatcher-systemet och stödjer både espeak-ng och Piper-röster via D-Bus. Det betyder att Alma, som är en Piper-röst, dyker upp automatiskt som valbar röst i Orca när speech-provider-piper är installerat.</p>
<p><img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/www.danielnylander.se/wp-content/spiel-alma-voice.png?ssl=1" alt="Spiel visar Alma-rösten som tillgänglig i terminalen på Ubuntu" style="max-width:100%; height:auto; border-radius:6px; border:1px solid #e0e0e0; margin:1em 0;"/></p>
<p>Vi har testat detta på Ubuntu 26.04 och Fedora 43. Spiel måste fortfarande byggas från källkod — det är inte paketerat i distributionerna ännu — men det fungerar. Alma hittas, väljs, och läser upp svensk text med sin vanliga varma röst, rakt in i Orca.</p>
<h3>Våra bidrag till Spiel-ekosystemet</h3>
<ul style="line-height:1.8;">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Svensk översättning av <a href="https://github.com/project-spiel/spiel-installer/pull/4">spiel-installer</a> (PR #4)</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Visa röststorlek före nedladdning i <a href="https://github.com/project-spiel/spiel-installer/pull/5">spiel-installer</a> (PR #5)</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> CI-testsvit för <a href="https://github.com/project-spiel/libspiel/pull/75">libspiel</a> (PR #75)</li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Förbättrad dokumentation för <a href="https://github.com/project-spiel/speech-provider-piper/pull/3">speech-provider-piper</a> (PR #3)</li>
</ul>
<p>Det här är fortfarande tidigt — Spiel är under aktiv utveckling och infrastrukturen mognar — men riktningen är tydlig. En naturlig svensk röst i GNOME:s tillgänglighetsstack, helt lokalt, utan molntjänster. Det är precis vad som behövs.</p>
<h2>Ladda ner</h2>
<p>Alma-rösten finns att ladda ner fritt:</p>
<ul style="line-height:1.8;">
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f917.png" alt="🤗" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <a href="https://huggingface.co/yeagersthlm/piper-voice-sv-alma">HuggingFace: yeagersthlm/piper-voice-sv-alma</a></li>
<li><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4e6.png" alt="📦" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <a href="https://github.com/yeager/piper-voices-sv">GitHub: yeager/piper-voices-sv</a></li>
</ul>
<p>Har du frågor eller vill testa rösten? Hör av dig!</p><p>The post <a href="https://www.danielnylander.se/2026/03/01/alma-en-svensk-tts-rost-for-barn-med-npf/">Alma — en svensk TTS-röst för barn med NPF</a> first appeared on <a href="https://www.danielnylander.se">Daniel Nylander.se</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.danielnylander.se/2026/03/01/alma-en-svensk-tts-rost-for-barn-med-npf/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		<enclosure url="https://www.danielnylander.se/wp-content/short1-default.wav" length="191648" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/short1-alma.wav" length="177824" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/short2-default.wav" length="217760" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/short2-alma.wav" length="206496" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/short3-default.wav" length="179872" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/short3-alma.wav" length="158880" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/long-default.wav" length="1290468" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/long-alma.wav" length="1151716" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/piper_nst_1.wav" length="139936" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/alma_1.wav" length="148128" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/piper_nst_2.wav" length="126624" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/alma_2.wav" length="139936" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/piper_nst_3.wav" length="154272" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/alma_3.wav" length="135328" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/piper_nst_4.wav" length="109216" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/alma_4.wav" length="96416" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_fore_1-1.wav" length="149784" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_fore_2-1.wav" length="109800" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_fore_3-1.wav" length="105012" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_fore_4-1.wav" length="87936" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_fore_5.wav" length="158348" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_fore_6.wav" length="177794" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_fore_7.wav" length="181508" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_fore_8.wav" length="118094" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_efter_1_prosody.wav" length="149676" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_efter_2_prosody.wav" length="103380" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_efter_3_prosody.wav" length="105394" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_efter_4_prosody.wav" length="88144" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_efter_5_prosody.wav" length="162284" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_efter_6_prosody.wav" length="162422" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_efter_7_prosody.wav" length="179040" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/espeak_efter_8_prosody.wav" length="122560" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/piper_nst_5.wav" length="154668" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/alma_5.wav" length="156716" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/piper_nst_6.wav" length="187948" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/alma_6.wav" length="149548" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/piper_nst_7.wav" length="200748" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/alma_7.wav" length="180268" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/piper_nst_8.wav" length="141868" type="audio/wav" />
<enclosure url="https://www.danielnylander.se/wp-content/alma_8.wav" length="129580" type="audio/wav" />

		<post-id xmlns="com-wordpress:feed-additions:1">1755</post-id>	</item>
		<item>
		<title>libvisio vs libvisio-ng: Why We Built a Pure Python Visio Parser</title>
		<link>https://www.danielnylander.se/2026/02/28/libvisio-vs-libvisio-ng-why-we-built-a-pure-python-visio-parser/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=libvisio-vs-libvisio-ng-why-we-built-a-pure-python-visio-parser</link>
					<comments>https://www.danielnylander.se/2026/02/28/libvisio-vs-libvisio-ng-why-we-built-a-pure-python-visio-parser/#respond</comments>
		
		<dc:creator><![CDATA[Daniel Nylander]]></dc:creator>
		<pubDate>Sat, 28 Feb 2026 16:41:42 +0000</pubDate>
				<category><![CDATA[Teknik]]></category>
		<guid isPermaLink="false">https://www.danielnylander.se/2026/02/28/libvisio-vs-libvisio-ng-why-we-built-a-pure-python-visio-parser/</guid>

					<description><![CDATA[<p>When I started building VSDView — a GTK4 viewer for Microsoft Visio files — I initially relied on libvisio, the C++ library from The Document Foundation (TDF) that powers Visio import in LibreOffice. It worked, sort of. But as I pushed it harder with real-world diagrams, the cracks became impossible to ignore. So I wrote [&#8230;]</p>
<p>The post <a href="https://www.danielnylander.se/2026/02/28/libvisio-vs-libvisio-ng-why-we-built-a-pure-python-visio-parser/">libvisio vs libvisio-ng: Why We Built a Pure Python Visio Parser</a> first appeared on <a href="https://www.danielnylander.se">Daniel Nylander.se</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>When I started building <a href="https://github.com/yeager/vsdview">VSDView</a> — a GTK4 viewer for Microsoft Visio files — I initially relied on <strong>libvisio</strong>, the C++ library from The Document Foundation (TDF) that powers Visio import in LibreOffice. It worked, sort of. But as I pushed it harder with real-world diagrams, the cracks became impossible to ignore.</p>
<p>So I wrote my own parser. It started as VSDView&#8217;s built-in rendering engine, and has now been extracted into a standalone library: <a href="https://github.com/yeager/libvisio-ng"><strong>libvisio-ng</strong></a>.</p>
<p>Here&#8217;s why, and what the difference looks like in practice.</p>
<h2>The Problem with libvisio (C++)</h2>
<p>libvisio is a reverse-engineered parser. It was built primarily for LibreOffice&#8217;s document import pipeline, not for high-fidelity rendering. The limitations become obvious quickly:</p>
<ul>
<li><strong>No theme support</strong> — Visio&#8217;s theme system (QuickStyles, accent colors) is completely ignored. Shapes that rely on themes render as black outlines.</li>
<li><strong>No fill colors</strong> — Most shape fills are simply missing. You get wireframes instead of diagrams.</li>
<li><strong>No connectors/arrows</strong> — The connection lines between shapes? Gone.</li>
<li><strong>No gradients or shadows</strong> — Visual polish completely absent.</li>
<li><strong>Broken text positioning</strong> — Text lands in the top-left corner instead of being centered in shapes. Colors are wrong. Multi-line text collapses.</li>
<li><strong>Dark theme destruction</strong> — If you&#8217;re running a dark desktop theme, libvisio renders white text on white backgrounds. Diagrams designed for light backgrounds become unreadable.</li>
</ul>
<h2>Side-by-Side Comparisons</h2>
<p>Let me show you what this actually looks like. Same Visio files, rendered by both engines.</p>
<h3>Network Architecture Diagram</h3>
<p>A typical network topology with shapes, connectors, and labels:</p>
<div style="display: flex; gap: 20px; flex-wrap: wrap; margin: 20px 0;">
<figure style="flex: 1; min-width: 300px;">
<img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/www.danielnylander.se/wp-content/builtin_network.png?ssl=1" alt="Network diagram rendered by libvisio-ng" style="width: 100%; border: 1px solid #ddd; border-radius: 4px;" /><figcaption style="text-align: center; font-style: italic; margin-top: 8px;">libvisio-ng (Python) — fills, connectors, proper text</figcaption></figure>
<figure style="flex: 1; min-width: 300px;">
<img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/www.danielnylander.se/wp-content/libvisio_network.png?ssl=1" alt="Network diagram rendered by libvisio C++" style="width: 100%; border: 1px solid #ddd; border-radius: 4px;" /><figcaption style="text-align: center; font-style: italic; margin-top: 8px;">libvisio (C++) — no fills, no connectors, broken text</figcaption></figure>
</div>
<p>The difference is stark. libvisio-ng renders the full diagram with colored shapes, directional arrows, and properly formatted text. libvisio gives you a skeleton — outlines with misplaced, barely-legible labels and zero connection lines.</p>
<h3>Comprehensive Feature Test</h3>
<p>A test file exercising gradients, shadows, transparency, dashed borders, thick outlines, and connectors:</p>
<div style="display: flex; gap: 20px; flex-wrap: wrap; margin: 20px 0;">
<figure style="flex: 1; min-width: 300px;">
<img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/www.danielnylander.se/wp-content/builtin_comprehensive.png?ssl=1" alt="Comprehensive test rendered by libvisio-ng" style="width: 100%; border: 1px solid #ddd; border-radius: 4px;" /><figcaption style="text-align: center; font-style: italic; margin-top: 8px;">libvisio-ng — gradients, shadows, transparency, arrows ✓</figcaption></figure>
<figure style="flex: 1; min-width: 300px;">
<img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/www.danielnylander.se/wp-content/libvisio_comprehensive.png?ssl=1" alt="Comprehensive test rendered by libvisio C++" style="width: 100%; border: 1px solid #ddd; border-radius: 4px;" /><figcaption style="text-align: center; font-style: italic; margin-top: 8px;">libvisio (C++) — missing fills, no shadows, no arrows</figcaption></figure>
</div>
<h3>Mikrotik Network Equipment Stencil</h3>
<p>A hardware stencil diagram with embedded images and detailed port layouts:</p>
<div style="display: flex; gap: 20px; flex-wrap: wrap; margin: 20px 0;">
<figure style="flex: 1; min-width: 300px;">
<img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/www.danielnylander.se/wp-content/builtin_mikrotik.png?ssl=1" alt="Mikrotik stencil rendered by libvisio-ng" style="width: 100%; border: 1px solid #ddd; border-radius: 4px;" /><figcaption style="text-align: center; font-style: italic; margin-top: 8px;">libvisio-ng — full stencil with embedded images</figcaption></figure>
<figure style="flex: 1; min-width: 300px;">
<img data-recalc-dims="1" decoding="async" src="https://i0.wp.com/www.danielnylander.se/wp-content/libvisio_mikrotik.png?ssl=1" alt="Mikrotik stencil rendered by libvisio C++" style="width: 100%; border: 1px solid #ddd; border-radius: 4px;" /><figcaption style="text-align: center; font-style: italic; margin-top: 8px;">libvisio (C++)</figcaption></figure>
</div>
<h2>Feature Comparison</h2>
<table style="width: 100%; border-collapse: collapse; margin: 20px 0;">
<thead>
<tr style="background: #f0f0f0;">
<th style="padding: 10px; text-align: left; border: 1px solid #ddd;">Feature</th>
<th style="padding: 10px; text-align: center; border: 1px solid #ddd;">libvisio (C++)</th>
<th style="padding: 10px; text-align: center; border: 1px solid #ddd;">libvisio-ng (Python)</th>
</tr>
</thead>
<tbody>
<tr>
<td style="padding: 8px; border: 1px solid #ddd;">Shape fills (solid)</td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr>
<td style="padding: 8px; border: 1px solid #ddd;">Gradient fills</td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr>
<td style="padding: 8px; border: 1px solid #ddd;">Theme/QuickStyle colors</td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr>
<td style="padding: 8px; border: 1px solid #ddd;">Drop shadows</td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr>
<td style="padding: 8px; border: 1px solid #ddd;">Transparency</td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr>
<td style="padding: 8px; border: 1px solid #ddd;">Connectors &#038; arrows</td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr>
<td style="padding: 8px; border: 1px solid #ddd;">Text centering/alignment</td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr>
<td style="padding: 8px; border: 1px solid #ddd;">Embedded images</td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Partial</td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr>
<td style="padding: 8px; border: 1px solid #ddd;">Background pages</td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr>
<td style="padding: 8px; border: 1px solid #ddd;">Layer visibility</td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr>
<td style="padding: 8px; border: 1px solid #ddd;">Master shape inheritance</td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Basic</td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Full</td>
</tr>
<tr>
<td style="padding: 8px; border: 1px solid #ddd;">StyleSheet cascade</td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Partial</td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr>
<td style="padding: 8px; border: 1px solid #ddd;">Binary .vsd support</td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr>
<td style="padding: 8px; border: 1px solid #ddd;">Zero C++ dependencies</td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
<tr>
<td style="padding: 8px; border: 1px solid #ddd;">pip install</td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
<td style="padding: 8px; text-align: center; border: 1px solid #ddd;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></td>
</tr>
</tbody>
</table>
<h2>Architecture: How libvisio-ng Works</h2>
<p>libvisio-ng is a pure Python library with minimal dependencies (<code>olefile</code> for binary .vsd format). For .vsdx files (the modern XML-based format), it has <strong>zero external dependencies</strong> — it reads the ZIP archive directly and parses the XML with Python&#8217;s standard library.</p>
<p>The rendering pipeline:</p>
<ol>
<li><strong>Parse ZIP</strong> — Extract pages, masters, themes, media, stylesheets, and relationships</li>
<li><strong>Resolve inheritance</strong> — Walk the master shape → stylesheet → theme chain to resolve every visual property</li>
<li><strong>Generate SVG</strong> — Convert Visio&#8217;s coordinate system to SVG paths, applying transforms, fills, gradients, shadows, and text layout</li>
<li><strong>Export</strong> — Optionally rasterize to PNG/PDF via CairoSVG or rsvg-convert</li>
</ol>
<p>The key insight that makes libvisio-ng work where libvisio doesn&#8217;t: <strong>Visio&#8217;s theme system is not optional</strong>. Modern .vsdx files store almost nothing as explicit colors — everything references themes via <code>THEMEVAL()</code>, <code>QuickStyleFillColor</code>, and accent indices. If you don&#8217;t resolve those references, you get black wireframes. libvisio-ng fully resolves the theme chain.</p>
<h2>Quick Start</h2>
<pre><code>pip install libvisio-ng

# Convert to SVG
from libvisio_ng import convert
svg_files = convert("diagram.vsdx", output_dir="output/")

# CLI
visio2svg convert diagram.vsdx -o output/
</code></pre>
<h2>Status</h2>
<p>libvisio-ng is at version 0.1.0 — early but already handling complex real-world diagrams significantly better than libvisio. It powers the rendering in <a href="https://github.com/yeager/vsdview">VSDView 0.4.6</a> and is available as a standalone library on <a href="https://github.com/yeager/libvisio-ng">GitHub</a>.</p>
<p>If you&#8217;ve been frustrated by libvisio&#8217;s output quality — or if you need to parse Visio files in Python without C++ dependencies — give it a try.</p><p>The post <a href="https://www.danielnylander.se/2026/02/28/libvisio-vs-libvisio-ng-why-we-built-a-pure-python-visio-parser/">libvisio vs libvisio-ng: Why We Built a Pure Python Visio Parser</a> first appeared on <a href="https://www.danielnylander.se">Daniel Nylander.se</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.danielnylander.se/2026/02/28/libvisio-vs-libvisio-ng-why-we-built-a-pure-python-visio-parser/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1747</post-id>	</item>
		<item>
		<title>makeBread — Recepthanterare för brödbakningsmaskiner</title>
		<link>https://www.danielnylander.se/2026/02/09/makebread-recepthanterare-for-brodbakningsmaskiner/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=makebread-recepthanterare-for-brodbakningsmaskiner</link>
					<comments>https://www.danielnylander.se/2026/02/09/makebread-recepthanterare-for-brodbakningsmaskiner/#respond</comments>
		
		<dc:creator><![CDATA[Daniel Nylander]]></dc:creator>
		<pubDate>Mon, 09 Feb 2026 07:45:04 +0000</pubDate>
				<category><![CDATA[Personligt]]></category>
		<category><![CDATA[Teknik]]></category>
		<guid isPermaLink="false">https://www.danielnylander.se/2026/02/09/makebread-recepthanterare-for-brodbakningsmaskiner/</guid>

					<description><![CDATA[<p>Nytt projekt! makeBread är en enkel och snygg recepthanterare för brödbakningsmaskiner, byggd med PySide6/Qt6. &#x1f35e; Vad kan den? 103 inbyggda recept — allt från klassiskt vitt bröd till glutenfritt och surdeg Sök och filtrera — fulltext med SQLite FTS5 Favoritmarkering &#x2b50; — markera dina bästa recept Slumpa recept &#x1f3b2; — när du inte kan bestämma [&#8230;]</p>
<p>The post <a href="https://www.danielnylander.se/2026/02/09/makebread-recepthanterare-for-brodbakningsmaskiner/">makeBread — Recepthanterare för brödbakningsmaskiner</a> first appeared on <a href="https://www.danielnylander.se">Daniel Nylander.se</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Nytt projekt! <strong>makeBread</strong> är en enkel och snygg recepthanterare för brödbakningsmaskiner, byggd med PySide6/Qt6.</p>
<h2><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f35e.png" alt="🍞" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Vad kan den?</h2>
<ul>
<li><strong>103 inbyggda recept</strong> — allt från klassiskt vitt bröd till glutenfritt och surdeg</li>
<li><strong>Sök och filtrera</strong> — fulltext med SQLite FTS5</li>
<li><strong>Favoritmarkering</strong> <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2b50.png" alt="⭐" class="wp-smiley" style="height: 1em; max-height: 1em;" /> — markera dina bästa recept</li>
<li><strong>Slumpa recept</strong> <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3b2.png" alt="🎲" class="wp-smiley" style="height: 1em; max-height: 1em;" /> — när du inte kan bestämma dig</li>
<li><strong>Enhetsomvandling</strong> — växla mellan metriskt, US cups och Imperial</li>
<li><strong>Skriv ut</strong> — snyggt formaterade utskrifter</li>
<li><strong>Bildstöd</strong> — lägg till egna bilder på resultatet</li>
<li><strong>Svenska och engelska</strong> — fullt översatt</li>
</ul>
<h2><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4e6.png" alt="📦" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Installation</h2>
<pre><code># Via pip/pipx
pipx install makebread

# Via apt (Debian/Ubuntu)
sudo apt install makebread

# Via dnf/yum (Fedora/RHEL)
sudo dnf install makebread</code></pre>
<h2><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4f8.png" alt="📸" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Varför?</h2>
<p>Alla receptappar är antingen överdrivet komplexa eller fulla av reklam. makeBread gör en sak och gör det bra: hålla koll på dina brödrecept. Ingen molntjänst, inga konton, bara en lokal SQLite-databas med dina recept.</p>
<p>Öppen källkod under GPL-3.0. Senaste versionen är <strong>v0.3.0</strong> med favoritfunktion och fullständig svensk översättning.</p>
<p>Källkod och releases: <a href="https://github.com/yeager/makebread">github.com/yeager/makebread</a></p><p>The post <a href="https://www.danielnylander.se/2026/02/09/makebread-recepthanterare-for-brodbakningsmaskiner/">makeBread — Recepthanterare för brödbakningsmaskiner</a> first appeared on <a href="https://www.danielnylander.se">Daniel Nylander.se</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.danielnylander.se/2026/02/09/makebread-recepthanterare-for-brodbakningsmaskiner/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1630</post-id>	</item>
		<item>
		<title>Debian- och RPM-repos för översättningsverktyg</title>
		<link>https://www.danielnylander.se/2026/02/04/eget-debian-repo-for-oversattningsverktyg/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=eget-debian-repo-for-oversattningsverktyg</link>
					<comments>https://www.danielnylander.se/2026/02/04/eget-debian-repo-for-oversattningsverktyg/#respond</comments>
		
		<dc:creator><![CDATA[Daniel Nylander]]></dc:creator>
		<pubDate>Wed, 04 Feb 2026 12:23:48 +0000</pubDate>
				<category><![CDATA[Teknik]]></category>
		<guid isPermaLink="false">https://www.danielnylander.se/2026/02/04/eget-debian-repo-for-oversattningsverktyg/</guid>

					<description><![CDATA[<p>Mina paketförråd för översättningsverktyg. Debian/Ubuntu (APT) echo "deb [trusted=yes] https://yeager.github.io/debian-repo stable main" &#124; sudo tee /etc/apt/sources.list.d/yeager.list sudo apt update Fedora/RHEL (DNF) sudo tee /etc/yum.repos.d/yeager.repo</p>
<p>The post <a href="https://www.danielnylander.se/2026/02/04/eget-debian-repo-for-oversattningsverktyg/">Debian- och RPM-repos för översättningsverktyg</a> first appeared on <a href="https://www.danielnylander.se">Daniel Nylander.se</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Mina paketförråd för översättningsverktyg.</p>
<h2>Debian/Ubuntu (APT)</h2>
<pre><code>echo "deb [trusted=yes] https://yeager.github.io/debian-repo stable main" | sudo tee /etc/apt/sources.list.d/yeager.list
sudo apt update</code></pre>
<h2>Fedora/RHEL (DNF)</h2>
<pre><code>sudo tee /etc/yum.repos.d/yeager.repo << EOF
[yeager]
name=Yeager Tools
baseurl=https://yeager.github.io/rpm-repo
enabled=1
gpgcheck=0
EOF</code></pre>
<h2>Paket</h2>
<table>
<thead>
<tr>
<th>Paket</th>
<th>Version</th>
<th>Beskrivning</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>l10n-lint</strong></td>
<td>1.8.0</td>
<td>Granska .po/.ts-filer (22 regler, testsvit)</td>
</tr>
<tr>
<td><strong>tp-lint</strong></td>
<td>1.7.0</td>
<td>Translation Project linting</td>
</tr>
<tr>
<td><strong>po-translate</strong></td>
<td>1.3.4</td>
<td>Massöversätt med AI/gratis tjänster</td>
</tr>
<tr>
<td><strong>po-diff</strong></td>
<td>1.0.0</td>
<td>Jämför PO-filer (11 språk)</td>
</tr>
</tbody>
</table>
<h2>po-diff</h2>
<p>Jämför två versioner av en översättningsfil:</p>
<pre><code>po-diff gammal.po ny.po
po-diff -f html -o diff.html gammal.po ny.po</code></pre>
<h2>Länkar</h2>
<ul>
<li><a href="https://github.com/yeager/l10n-lint">l10n-lint</a></li>
<li><a href="https://github.com/yeager/tp-lint">tp-lint</a></li>
<li><a href="https://github.com/yeager/po-translate">po-translate</a></li>
<li><a href="https://github.com/yeager/po-diff">po-diff</a></li>
</ul><p>The post <a href="https://www.danielnylander.se/2026/02/04/eget-debian-repo-for-oversattningsverktyg/">Debian- och RPM-repos för översättningsverktyg</a> first appeared on <a href="https://www.danielnylander.se">Daniel Nylander.se</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.danielnylander.se/2026/02/04/eget-debian-repo-for-oversattningsverktyg/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1605</post-id>	</item>
		<item>
		<title>Kodi Subtitle Translator v0.8.0 – nu med stöd för externa undertexter</title>
		<link>https://www.danielnylander.se/2026/01/31/automatisk-oversattning-av-undertexter-i-kodi/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=automatisk-oversattning-av-undertexter-i-kodi</link>
					<comments>https://www.danielnylander.se/2026/01/31/automatisk-oversattning-av-undertexter-i-kodi/#respond</comments>
		
		<dc:creator><![CDATA[Daniel Nylander]]></dc:creator>
		<pubDate>Sat, 31 Jan 2026 17:58:28 +0000</pubDate>
				<category><![CDATA[Översättningar]]></category>
		<category><![CDATA[Personligt]]></category>
		<category><![CDATA[Teknik]]></category>
		<guid isPermaLink="false">https://www.danielnylander.se/?p=1563</guid>

					<description><![CDATA[<p>Kodi Subtitle Translator är ett gratis tillägg som automatiskt översätter undertexter i MKV, MP4 och andra mediefiler. Version 0.8.0 lägger till stöd för externa undertextfiler (.srt, .ass, .vtt) och 25 språk med DeepL, Google, LibreTranslate och fler.</p>
<p>The post <a href="https://www.danielnylander.se/2026/01/31/automatisk-oversattning-av-undertexter-i-kodi/">Kodi Subtitle Translator v0.8.0 – nu med stöd för externa undertexter</a> first appeared on <a href="https://www.danielnylander.se">Daniel Nylander.se</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Jag har släppt <strong>version 0.8.0</strong> av Kodi Subtitle Translator med en efterfrågad funktion: <strong>stöd för externa undertextfiler</strong>!</p>
<h2>Nytt i v0.8.0</h2>
<ul>
<li><strong>Externa undertexter</strong> – Översätt .srt, .ass, .ssa och .vtt-filer som ligger bredvid din mediefil</li>
<li><strong>Välj källa</strong> – Dialog för att välja mellan inbäddade undertexter, externa filer eller bläddra till egen fil</li>
<li><strong>Smartare detektering</strong> – Hittar automatiskt undertextfiler med samma namn som videon</li>
</ul>
<h2>Så fungerar det</h2>
<p>När du spelar upp en film eller serie i Kodi:</p>
<ol>
<li>Tillägget detekterar om det saknas undertexter på ditt språk</li>
<li>Du får välja källa: inbäddade, externa eller bläddra</li>
<li>Undertexterna översätts automatiskt via din valda tjänst</li>
<li>Resultatet cachas så du slipper vänta nästa gång</li>
</ol>
<h2>Översättningstjänster</h2>
<h3>Gratis (ingen API-nyckel)</h3>
<ul>
<li><strong>LibreTranslate</strong> – Öppen källkod, kan självhostas</li>
<li><strong>MyMemory</strong> – 1000 ord/dag gratis</li>
<li><strong>Lingva Translate</strong> – Google Translate utan spårning</li>
</ul>
<h3>Betalda (bättre kvalitet)</h3>
<ul>
<li><strong>DeepL</strong> – Bäst kvalitet för europeiska språk</li>
<li><strong>DeepL Free</strong> – 500k tecken/månad gratis</li>
<li><strong>Google Cloud Translation</strong></li>
<li><strong>Microsoft Translator</strong></li>
</ul>
<h2>25 språk</h2>
<p>Tillägget stöder översättning till och från 25 språk inklusive svenska, norska, danska, finska, tyska, franska, spanska, italienska, portugisiska, polska, nederländska, ryska, japanska, kinesiska och koreanska.</p>
<h2>Funktioner</h2>
<ul>
<li><strong>Automatisk detektering</strong> – Upptäcker saknade undertexter</li>
<li><strong>Smart caching</strong> – Översättningar sparas lokalt</li>
<li><strong>Flera format</strong> – SRT, ASS/SSA, WebVTT</li>
<li><strong>Bevarad formatering</strong> – Timing och styling behålls</li>
<li><strong>FFmpeg-integration</strong> – Extraherar inbäddade undertexter</li>
</ul>
<h2>Installation</h2>
<ol>
<li>Ladda ner ZIP från <a href="https://github.com/yeager/kodi-subtitle-translator/releases" target="_blank" rel="noopener">GitHub Releases</a></li>
<li>I Kodi: <em>Inställningar → Tillägg → Installera från ZIP-fil</em></li>
<li>Konfigurera språk och översättningstjänst i tilläggsinställningarna</li>
</ol>
<h2>Källkod</h2>
<p>Gratis och öppen källkod (GPL-3.0):</p>
<p><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f517.png" alt="🔗" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <a href="https://github.com/yeager/kodi-subtitle-translator" target="_blank" rel="noopener"><strong>github.com/yeager/kodi-subtitle-translator</strong></a></p>
<p><em>Feedback, buggrapporter och pull requests är välkomna!</em></p><p>The post <a href="https://www.danielnylander.se/2026/01/31/automatisk-oversattning-av-undertexter-i-kodi/">Kodi Subtitle Translator v0.8.0 – nu med stöd för externa undertexter</a> first appeared on <a href="https://www.danielnylander.se">Daniel Nylander.se</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.danielnylander.se/2026/01/31/automatisk-oversattning-av-undertexter-i-kodi/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1563</post-id>	</item>
		<item>
		<title>Översättning av Boxee</title>
		<link>https://www.danielnylander.se/2011/01/26/oversattning-av-boxee/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=oversattning-av-boxee</link>
					<comments>https://www.danielnylander.se/2011/01/26/oversattning-av-boxee/#respond</comments>
		
		<dc:creator><![CDATA[Daniel Nylander]]></dc:creator>
		<pubDate>Wed, 26 Jan 2011 22:37:44 +0000</pubDate>
				<category><![CDATA[Översättningar]]></category>
		<category><![CDATA[Teknik]]></category>
		<guid isPermaLink="false">http://www.danielnylander.se/?p=547</guid>

					<description><![CDATA[<p>Jag har nu börjat att översätta mediaspelaren Boxee. Boxee är en funktionsrik mediaspelare baserad på öppen källkod (XBMC) och kan köras på datorer och dedicerade hårdvaruplattformar (D-Link Boxee Box, Iomega TV with Boxee samt upplåsta Apple TV). Det stora utbudet av anpassade program gör också detta till en intressant mediaspelare.</p>
<p>The post <a href="https://www.danielnylander.se/2011/01/26/oversattning-av-boxee/">Översättning av Boxee</a> first appeared on <a href="https://www.danielnylander.se">Daniel Nylander.se</a>.</p>]]></description>
										<content:encoded><![CDATA[<p>Jag har nu börjat att översätta mediaspelaren <a href="http://www.boxee.tv/" target="_blank" rel="noopener">Boxee</a>.</p>
<p>Boxee är en funktionsrik mediaspelare baserad på öppen källkod (<a href="http://xbmc.org/" target="_blank" rel="noopener">XBMC</a>) och kan köras på datorer och dedicerade hårdvaruplattformar (<a href="http://www.dlink.com/boxee/" target="_blank" rel="noopener">D-Link Boxee Box</a>, <a href="http://www.iomega.com/iomegatv-media-center/index.html" target="_blank" rel="noopener">Iomega TV with Boxee</a> samt upplåsta <a href="http://howto.wired.com/wiki/Hack_Your_Apple_TV_With_Boxee" target="_blank" rel="noopener">Apple TV</a>). Det stora utbudet av anpassade program gör också detta till en intressant mediaspelare.</p>
<p><img loading="lazy" decoding="async" class="alignnone" src="/pics/boxee2.png" alt="" width="690" height="431" /></p>
<p><span id="more-547"></span><img loading="lazy" decoding="async" class="alignnone" src="/pics/boxee1.png" alt="" width="690" height="431" /></p><p>The post <a href="https://www.danielnylander.se/2011/01/26/oversattning-av-boxee/">Översättning av Boxee</a> first appeared on <a href="https://www.danielnylander.se">Daniel Nylander.se</a>.</p>]]></content:encoded>
					
					<wfw:commentRss>https://www.danielnylander.se/2011/01/26/oversattning-av-boxee/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">547</post-id>	</item>
	</channel>
</rss>
