<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Shiqiang Wang</title>
    <description>The latest articles on DEV Community by Shiqiang Wang (@shuijingwan).</description>
    <link>https://dev.to/shuijingwan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4126023%2Fd50ac03f-7c0c-4ff5-af7c-fe02fbe9a22a.png</url>
      <title>DEV Community: Shiqiang Wang</title>
      <link>https://dev.to/shuijingwan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shuijingwan"/>
    <language>en</language>
    <item>
      <title>How I Maintain A Tour of Go in 11 Languages</title>
      <dc:creator>Shiqiang Wang</dc:creator>
      <pubDate>Tue, 15 Sep 2026 10:05:46 +0000</pubDate>
      <link>https://dev.to/shuijingwan/how-i-maintain-a-tour-of-go-in-11-languages-ahl</link>
      <guid>https://dev.to/shuijingwan/how-i-maintain-a-tour-of-go-in-11-languages-ahl</guid>
      <description>&lt;p&gt;A Tour of Go is one of the first resources many developers encounter when learning Go.&lt;/p&gt;

&lt;p&gt;It is interactive, concise, and closely connected to the Go ecosystem. But for developers who are more comfortable learning technical concepts in their native language, language can still be a barrier.&lt;/p&gt;

&lt;p&gt;That is why I started maintaining &lt;strong&gt;go-tour-i18n&lt;/strong&gt;, an unofficial, community-maintained multilingual version of A Tour of Go.&lt;/p&gt;

&lt;p&gt;Today, the project has &lt;strong&gt;11 translations running in production&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Brazilian Portuguese&lt;/li&gt;
&lt;li&gt;Dutch&lt;/li&gt;
&lt;li&gt;French&lt;/li&gt;
&lt;li&gt;German&lt;/li&gt;
&lt;li&gt;Italian&lt;/li&gt;
&lt;li&gt;Japanese&lt;/li&gt;
&lt;li&gt;Korean&lt;/li&gt;
&lt;li&gt;Simplified Chinese&lt;/li&gt;
&lt;li&gt;Spanish&lt;/li&gt;
&lt;li&gt;Swedish&lt;/li&gt;
&lt;li&gt;Turkish&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project is open source:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/shuijingwan/go-tour-i18n" rel="noopener noreferrer"&gt;https://github.com/shuijingwan/go-tour-i18n&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Several of these translations are also linked from the official A Tour of Go localization page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://go.dev/tour/welcome/2" rel="noopener noreferrer"&gt;https://go.dev/tour/welcome/2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The project is still unofficial and community-maintained.&lt;/p&gt;

&lt;p&gt;But after maintaining more and more languages, I learned that translating the text itself is only a small part of the work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Translation is the easy part
&lt;/h2&gt;

&lt;p&gt;At first, a translation project can look simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Take the English source.&lt;/li&gt;
&lt;li&gt;Translate it.&lt;/li&gt;
&lt;li&gt;Publish the result.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That works until the upstream project changes.&lt;/p&gt;

&lt;p&gt;Then other problems begin to appear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;terminology becomes inconsistent;&lt;/li&gt;
&lt;li&gt;code or identifiers are accidentally changed;&lt;/li&gt;
&lt;li&gt;translated pages fall behind upstream;&lt;/li&gt;
&lt;li&gt;structurally valid translations still sound unnatural;&lt;/li&gt;
&lt;li&gt;metadata and UI text do not match the translated course;&lt;/li&gt;
&lt;li&gt;a new language works locally but is incomplete in production.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a technical tutorial, a translation can be grammatically correct and still be technically wrong.&lt;/p&gt;

&lt;p&gt;It can also pass every structural check and still be poor writing.&lt;/p&gt;

&lt;p&gt;So I eventually stopped thinking of this project as a collection of translated pages.&lt;/p&gt;

&lt;p&gt;I started treating it as a &lt;strong&gt;translation, review, synchronization, and publishing system&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  TranslationUnit is the basic unit of work
&lt;/h2&gt;

&lt;p&gt;The project uses a concept called a &lt;strong&gt;TranslationUnit&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For a Tour page, one TranslationUnit is a complete top-level page section.&lt;/p&gt;

&lt;p&gt;For an eligible Go example, the TranslationUnit is the complete Go source file, while only permitted natural-language comments are translated.&lt;/p&gt;

&lt;p&gt;I do not split a page into arbitrary text fragments just because smaller pieces are easier for a model to translate.&lt;/p&gt;

&lt;p&gt;Keeping the unit complete makes it possible to associate translation work with a stable source identity and then validate, review, revise, and promote that unit as a whole.&lt;/p&gt;

&lt;p&gt;This makes it easier to answer questions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which version of the English source was translated?&lt;/li&gt;
&lt;li&gt;Which glossary was used?&lt;/li&gt;
&lt;li&gt;Did the candidate pass mechanical validation?&lt;/li&gt;
&lt;li&gt;Was its language quality actually reviewed?&lt;/li&gt;
&lt;li&gt;Has the source changed since the translation was produced?&lt;/li&gt;
&lt;li&gt;Is the version currently in production still valid?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once the project expanded beyond one language, those questions became much more important.&lt;/p&gt;

&lt;h2&gt;
  
  
  Terminology comes before translation
&lt;/h2&gt;

&lt;p&gt;Every locale has its own glossary.&lt;/p&gt;

&lt;p&gt;This turned out to matter much more than I expected.&lt;/p&gt;

&lt;p&gt;Technical terminology cannot always be handled by literal translation.&lt;/p&gt;

&lt;p&gt;Some words should remain in English.&lt;/p&gt;

&lt;p&gt;Some have well-established translations in one language but not another.&lt;/p&gt;

&lt;p&gt;A term that feels natural to a Japanese developer may need a completely different treatment in Brazilian Portuguese, German, or French.&lt;/p&gt;

&lt;p&gt;Because of that, I do not create a new locale by simply machine-translating another locale's glossary.&lt;/p&gt;

&lt;p&gt;Terminology decisions are made for each language independently.&lt;/p&gt;

&lt;p&gt;The glossary is then treated as part of the translation input rather than as a cleanup step after translation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Validation is not language quality
&lt;/h2&gt;

&lt;p&gt;This is probably the most important lesson from the project.&lt;/p&gt;

&lt;p&gt;The project performs automatic validation designed to protect things that translation must not break, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;code;&lt;/li&gt;
&lt;li&gt;Go identifiers;&lt;/li&gt;
&lt;li&gt;URLs;&lt;/li&gt;
&lt;li&gt;link targets;&lt;/li&gt;
&lt;li&gt;directives;&lt;/li&gt;
&lt;li&gt;protected tokens;&lt;/li&gt;
&lt;li&gt;preformatted content;&lt;/li&gt;
&lt;li&gt;structural relationships;&lt;/li&gt;
&lt;li&gt;machine-readable semantics.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those checks are necessary.&lt;/p&gt;

&lt;p&gt;But passing them does &lt;strong&gt;not&lt;/strong&gt; mean that a translation is good.&lt;/p&gt;

&lt;p&gt;A sentence can preserve every protected token and still be awkward.&lt;/p&gt;

&lt;p&gt;It can preserve the exact technical structure while expressing the idea incorrectly.&lt;/p&gt;

&lt;p&gt;It can even be technically understandable while sounding obviously machine-translated to a native speaker.&lt;/p&gt;

&lt;p&gt;So the workflow deliberately separates mechanical validation from language-quality review.&lt;/p&gt;

&lt;p&gt;A simplified version of the current process looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;glossary preparation
→ translation
→ automatic validation
→ Candidate Snapshot
→ language quality review
→ machine finalization
→ promotion
→ deployment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Automatic validation answers a question like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is this candidate structurally safe?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Language review answers a different question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is this translation actually good enough to publish?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I do not treat “validator passed” as equivalent to “translation finished.”&lt;/p&gt;

&lt;p&gt;That distinction becomes increasingly important as AI makes translation faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI makes translation faster, but review matters more
&lt;/h2&gt;

&lt;p&gt;AI makes a project like this possible at a scale that would have been much harder for me to maintain alone.&lt;/p&gt;

&lt;p&gt;But I do not treat model output as final content.&lt;/p&gt;

&lt;p&gt;The current workflow uses AI for work that genuinely requires language understanding, while deterministic tooling handles things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;source identity;&lt;/li&gt;
&lt;li&gt;structural validation;&lt;/li&gt;
&lt;li&gt;protected content;&lt;/li&gt;
&lt;li&gt;workflow state;&lt;/li&gt;
&lt;li&gt;stale detection;&lt;/li&gt;
&lt;li&gt;finalization gates;&lt;/li&gt;
&lt;li&gt;promotion;&lt;/li&gt;
&lt;li&gt;production verification.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After automatic validation, every TranslationUnit still needs a language-quality decision before it can be promoted.&lt;/p&gt;

&lt;p&gt;If a translation has a language problem, the correct response is to revise the translation.&lt;/p&gt;

&lt;p&gt;The validator is not changed simply to make a poor translation pass.&lt;/p&gt;

&lt;p&gt;That sounds obvious, but when automation becomes sophisticated, it is surprisingly easy to confuse a successful pipeline with a successful result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Upstream synchronization matters
&lt;/h2&gt;

&lt;p&gt;A translation of A Tour of Go is not very useful if it slowly becomes a translation of an old version of A Tour of Go.&lt;/p&gt;

&lt;p&gt;The project therefore tracks the official Go upstream.&lt;/p&gt;

&lt;p&gt;When source content changes, the affected source identity changes as well.&lt;/p&gt;

&lt;p&gt;That gives the project a deterministic way to identify translated content that needs attention instead of rebuilding every language blindly.&lt;/p&gt;

&lt;p&gt;With one language, manual comparison may be manageable.&lt;/p&gt;

&lt;p&gt;With eleven languages, and potentially many more in the future, it needs to be systematic.&lt;/p&gt;

&lt;p&gt;The larger the language set becomes, the more important stale detection becomes.&lt;/p&gt;

&lt;h2&gt;
  
  
  A language is more than its lesson text
&lt;/h2&gt;

&lt;p&gt;Another lesson was that translating course pages is not enough.&lt;/p&gt;

&lt;p&gt;A real locale also has other user-facing surfaces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;navigation;&lt;/li&gt;
&lt;li&gt;shared UI messages;&lt;/li&gt;
&lt;li&gt;language selectors;&lt;/li&gt;
&lt;li&gt;article metadata;&lt;/li&gt;
&lt;li&gt;course metadata;&lt;/li&gt;
&lt;li&gt;SEO descriptions;&lt;/li&gt;
&lt;li&gt;runtime messages;&lt;/li&gt;
&lt;li&gt;public URLs;&lt;/li&gt;
&lt;li&gt;production configuration.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A locale can have excellent lesson translations and still feel unfinished if the surrounding interface contains English leftovers or inconsistent terminology.&lt;/p&gt;

&lt;p&gt;So after the TranslationUnits are promoted, the project performs a separate locale-level surface review.&lt;/p&gt;

&lt;p&gt;This is intentionally different from TranslationUnit quality review.&lt;/p&gt;

&lt;p&gt;One checks individual translation units.&lt;/p&gt;

&lt;p&gt;The other checks whether the complete locale works as a coherent product.&lt;/p&gt;

&lt;h2&gt;
  
  
  Production is part of the workflow
&lt;/h2&gt;

&lt;p&gt;I also wanted each translation to be more than a directory of files in a Git repository.&lt;/p&gt;

&lt;p&gt;Each completed locale becomes a real, independently accessible Tour site.&lt;/p&gt;

&lt;p&gt;That introduces another set of concerns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;building a complete locale;&lt;/li&gt;
&lt;li&gt;previewing it;&lt;/li&gt;
&lt;li&gt;checking public routes;&lt;/li&gt;
&lt;li&gt;deploying it;&lt;/li&gt;
&lt;li&gt;configuring its public hostname;&lt;/li&gt;
&lt;li&gt;validating production behavior;&lt;/li&gt;
&lt;li&gt;handling search engines and sitemaps;&lt;/li&gt;
&lt;li&gt;keeping future deployments repeatable.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is one reason the project gradually became much more of an engineering project than I originally expected.&lt;/p&gt;

&lt;p&gt;Translation is still at its center.&lt;/p&gt;

&lt;p&gt;But reliable multilingual publishing requires much more than translation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I keep the project unofficial
&lt;/h2&gt;

&lt;p&gt;Some of the translations are linked from the official A Tour of Go localization page, which has been very encouraging.&lt;/p&gt;

&lt;p&gt;But I still describe the project clearly as &lt;strong&gt;unofficial and community-maintained&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It is not maintained by Google, the Go team, or go.dev.&lt;/p&gt;

&lt;p&gt;The original Tour source comes from the official Go upstream, while this repository maintains the translation, validation, review, synchronization, and production workflow around those localized versions.&lt;/p&gt;

&lt;p&gt;I think making that distinction explicit is important for an open-source community project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the project is today
&lt;/h2&gt;

&lt;p&gt;There are currently &lt;strong&gt;11 translations in production&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Brazilian Portuguese&lt;/li&gt;
&lt;li&gt;Dutch&lt;/li&gt;
&lt;li&gt;French&lt;/li&gt;
&lt;li&gt;German&lt;/li&gt;
&lt;li&gt;Italian&lt;/li&gt;
&lt;li&gt;Japanese&lt;/li&gt;
&lt;li&gt;Korean&lt;/li&gt;
&lt;li&gt;Simplified Chinese&lt;/li&gt;
&lt;li&gt;Spanish&lt;/li&gt;
&lt;li&gt;Swedish&lt;/li&gt;
&lt;li&gt;Turkish&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And I am continuing to add more.&lt;/p&gt;

&lt;p&gt;The long-term challenge is no longer simply:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How quickly can I translate another language?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is increasingly:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How can I add languages without making the existing ones harder to maintain?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That means continuing to improve the workflow for terminology, translation, review, stale detection, upstream synchronization, metadata, production, and future maintenance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feedback is especially valuable
&lt;/h2&gt;

&lt;p&gt;The project is here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/shuijingwan/go-tour-i18n" rel="noopener noreferrer"&gt;https://github.com/shuijingwan/go-tour-i18n&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The official A Tour of Go localization page is here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://go.dev/tour/welcome/2" rel="noopener noreferrer"&gt;https://go.dev/tour/welcome/2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are a native speaker of one of the supported languages, feedback is especially welcome.&lt;/p&gt;

&lt;p&gt;The most useful feedback is often not about obvious broken code or missing text.&lt;/p&gt;

&lt;p&gt;It is about sentences that are technically correct but still do not sound like something a developer would naturally say in that language.&lt;/p&gt;

&lt;p&gt;Automation can find many classes of problems.&lt;/p&gt;

&lt;p&gt;That kind of language judgment is much harder.&lt;/p&gt;

&lt;p&gt;And as the project grows, it is also one of the things I value most.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Disclosure: I used AI assistance to help organize and edit this article. The project, implementation experience, workflow decisions, and conclusions described here are my own.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>opensource</category>
      <category>showdev</category>
      <category>i18n</category>
    </item>
  </channel>
</rss>
