<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ translation - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ translation - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 19 May 2026 10:29:16 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/translation/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Localize Your Websites with Crowdin ]]>
                </title>
                <description>
                    <![CDATA[ We just posted a course on the freeCodeCamp Community YouTube channel that will teach you how to use Crowdin, a leading cloud-based localization platform. The course was created by Estefania Cassingena Navone. She's an experienced teacher and also ru... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/localize-websites-with-crowdin/</link>
                <guid isPermaLink="false">66b20586125aeccef6f65cf2</guid>
                
                    <category>
                        <![CDATA[ localization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ translation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ youtube ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Beau Carnes ]]>
                </dc:creator>
                <pubDate>Wed, 13 Mar 2024 18:00:11 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/03/crowdin.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>We just posted a course on the freeCodeCamp Community YouTube channel that will teach you how to use Crowdin, a leading cloud-based localization platform. The course was created by Estefania Cassingena Navone. She's an experienced teacher and also runs the freeCodeCamp Español channel.</p>
<h2 id="heading-whats-crowdin">What's Crowdin?</h2>
<p>Crowdin is a cloud-based solution designed to facilitate the translation and localization process for digital content, including websites and mobile apps. It stands out for its collaborative features, allowing multiple contributors to work on a project simultaneously, ensuring both consistency and efficiency in translating and localizing content for different regions and languages.</p>
<p>This course is designed to be a comprehensive guide for anyone looking to master Crowdin and enhance their localization strategies. Whether you're a developer, a content creator, or a project manager, this course will equip you with the knowledge and skills needed to utilize Crowdin effectively.</p>
<p>Here are some key highlights of the course:</p>
<ul>
<li><strong>Introduction to Localization</strong>: Understand the fundamentals of localization and its importance in today's globalized digital world.</li>
<li><strong>Crowdin Explained</strong>: Dive deep into what Crowdin is, its ecosystem, and how it can streamline your localization process.</li>
<li><strong>Hands-on Tutorials</strong>: From creating a Crowdin account to uploading files and starting translations, the course provides step-by-step tutorials on every aspect of the platform.</li>
<li><strong>Advanced Features</strong>: Learn about Crowdin's advanced features, including translation memory, glossary, quality assurance checks, and much more.</li>
<li><strong>Practical Applications</strong>: The course covers real-world applications, like integrating Crowdin with Google Drive, GitHub, and even localizing a React app using Crowdin's powerful tools.</li>
</ul>
<p>And here is the full list of sections:</p>
<ul>
<li>Introduction</li>
<li>freeCodeCamp's Localization Effort</li>
<li>What is Localization?</li>
<li>Importance of Localization</li>
<li>Translation vs. Localization</li>
<li>Localized Resources</li>
<li>Frequently Used File Formats</li>
<li>Localization Terminology</li>
<li>Introduction to Crowdin</li>
<li>Important Terminology for Crowdin</li>
<li>Create a Crowdin Account </li>
<li>Log in and Log out</li>
<li>Create a Crowdin Enterprise Account </li>
<li>Activate the Free Plan</li>
<li>Customize your Profile</li>
<li>Create a Project</li>
<li>Project Overview</li>
<li>Project Settings</li>
<li>Delete a Project</li>
<li>Upload Files</li>
<li>Start Translating</li>
<li>Translation Editor</li>
<li>Translation Editor Modes</li>
<li>Go to Another File </li>
<li>Show and Approve Strings</li>
<li>Translate RTL Languages</li>
<li>Translation Editor Settings </li>
<li>Keyboard Shortcuts</li>
<li>Download the Translated Files</li>
<li>Translation Memory</li>
<li>Glossary</li>
<li>Quality Assurance (QA) Checks</li>
<li>Upload Existing Translations</li>
<li>Pre-Translation</li>
<li>Offline Translation</li>
<li>Invite Project Members </li>
<li>Project Managers</li>
<li>Tasks </li>
<li>Project Reports</li>
<li>Conversations </li>
<li>Integrations (Google Drive as an example)</li>
<li>More Integrations</li>
<li>Crowdin Enterprise for Organizations</li>
<li>Groups in Crowdin Enterprise   </li>
<li>Projects in Crowdin Enterprise</li>
<li>Visual Studio Code Extension  </li>
<li>Translate a React App </li>
<li>Introduction to react-i18next  </li>
<li>Crowdin GitHub Integration </li>
<li>JS Proxy Translator Integration for Static Websites</li>
<li>Crowdin In-Context Localization for Web</li>
<li>Crowdin for Contributors</li>
<li>i18next and Crowdin documentation</li>
<li>Final Words</li>
</ul>
<p>Localization is not just about translating text – it's about adapting your content to resonate with different cultures and languages. This course goes beyond the basics of translation, teaching how to leverage Crowdin to its full potential. Watch the full course on <a target="_blank" href="https://www.youtube.com/watch?v=qTEag3J1ebY">the freeCodeCamp.org YouTube channel</a> (8-hour watch).</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/qTEag3J1ebY" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Localization Guide – How to Translate Your Website Into Different World Languages [Full Book] ]]>
                </title>
                <description>
                    <![CDATA[ Welcome! In a global world where information is available to everyone in just a few clicks, adapting your website and resources to other languages and cultures is essential to succeed. This book will teach you the fundamentals of localization and how... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/localization-book-how-to-translate-your-website/</link>
                <guid isPermaLink="false">66b1f85841fdb67461b85342</guid>
                
                    <category>
                        <![CDATA[ book ]]>
                    </category>
                
                    <category>
                        <![CDATA[ i18n ]]>
                    </category>
                
                    <category>
                        <![CDATA[ localization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ translation ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Estefania Cassingena Navone ]]>
                </dc:creator>
                <pubDate>Thu, 28 Sep 2023 18:17:44 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/09/Localization-Course-Handbook-Cover-Version-4.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Welcome! In a global world where information is available to everyone in just a few clicks, adapting your website and resources to other languages and cultures is essential to succeed.</p>
<p>This book will teach you the fundamentals of localization and how to translate your website to reach a global community of users without any language barrier.</p>
<h2 id="heading-where-to-start">🔹 Where to Start</h2>
<p>But where do you start?</p>
<p>That is an important question that managers often ask themselves when they decide to adapt their products and go multilingual.</p>
<p>In this book, you will learn all the fundamentals of localization from a conceptual and practical point of view.</p>
<p>You will learn how to localize files, websites, games, and any other type of resource on <a target="_blank" href="https://crowdin.com/">Crowdin</a>, the cloud-based localization management platform that powers freeCodeCamp's localization effort.</p>
<p><strong>We will cover the following:</strong> </p>
<ul>
<li><a class="post-section-overview" href="#heading-freecodecamp-as-a-real-world-example">freeCodeCamp as a Real-World Example</a></li>
<li><a class="post-section-overview" href="#heading-a-localization-effort-by-humans-for-humans">A Localization Effort by Humans, for Humans</a></li>
<li><a class="post-section-overview" href="#heading-what-are-the-fundamentals-of-localization">What are the Fundamentals of Localization?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-localization">What is Localization?</a></li>
<li><a class="post-section-overview" href="#heading-translation-vs-localization">Translation vs Localization</a></li>
<li><a class="post-section-overview" href="#heading-importance-of-localization">Importance of Localization</a></li>
<li><a class="post-section-overview" href="#heading-localization-terminologies">Localization Terminologies</a></li>
<li><a class="post-section-overview" href="#heading-translation-vs-proofreading">Translating vs Proofreading</a></li>
<li><a class="post-section-overview" href="#heading-what-types-of-resources-can-be-localized">What Types of Resources Can Be Localized?</a></li>
<li><a class="post-section-overview" href="#heading-common-file-formats">Common File Formats</a></li>
<li><a class="post-section-overview" href="#heading-localization-phases-and-roles">Localization Phases and Roles</a></li>
<li><a class="post-section-overview" href="#heading-crowdin-fundamentals-for-localization-projects">Crowdin Fundamentals for Localization Projects</a></li>
<li><a class="post-section-overview" href="#important-terminologies-for-crowdin">Important Terminologies for Crowdin</a></li>
<li><a class="post-section-overview" href="#heading-getting-started-with-crowdin">Getting Started with Crowdin</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-a-crowdin-account">How to Create a Crowdin Account</a></li>
<li><a class="post-section-overview" href="#heading-how-to-customize-your-crowdin-profile">How to Customize your Crowdin Profile</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-a-project-on-crowdin">How to Create a Project on Crowdin</a></li>
<li><a class="post-section-overview" href="#heading-project-overview">Project Overview</a></li>
<li><a class="post-section-overview" href="#heading-how-to-customize-your-project-settings-in-crowdin">How to Customize your Project Settings in Crowdin</a></li>
<li><a class="post-section-overview" href="#heading-how-to-delete-a-project-in-crowdin">How to Delete a Project in Crowdin</a></li>
<li><a class="post-section-overview" href="#heading-how-to-upload-files-to-your-crowdin-project">How to Upload Files to your Crowdin Project</a></li>
<li><a class="post-section-overview" href="#heading-how-to-start-translating">How to Start Translating</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-the-translation-editor">How to Use the Translation Editor</a></li>
<li><a class="post-section-overview" href="#heading-translation-editor-modes">Translation Editor Modes</a></li>
<li><a class="post-section-overview" href="#heading-how-to-switch-to-another-file">How to Switch to Another File</a></li>
<li><a class="post-section-overview" href="#heading-how-to-view-all-strings">How to View All Strings</a></li>
<li><a class="post-section-overview" href="#heading-how-to-translate-rtl-languages">How to Translate RTL Languages</a></li>
<li><a class="post-section-overview" href="#heading-how-to-download-the-translated-files">How to Download the Translated File(s)</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-translation-memory-tm">How to Use Translation Memory (TM)</a></li>
<li><a class="post-section-overview" href="#heading-glossary">Glossary</a></li>
<li><a class="post-section-overview" href="#heading-quality-assurance-qa-checks-in-crowdin">Quality Assurance (QA) Checks in Crowdin</a></li>
<li><a class="post-section-overview" href="#heading-how-to-upload-existing-translations">How to Uploading Existing Translations</a></li>
<li><a class="post-section-overview" href="#heading-how-to-pre-translate-your-project">How to Pre-Translate your Project</a></li>
<li><a class="post-section-overview" href="#heading-offline-translation">Offline Translation</a></li>
<li><a class="post-section-overview" href="#heading-exploring-public-projects">Exploring Public Projects</a></li>
<li><a class="post-section-overview" href="#heading-crowdin-for-teams-and-organizations">Crowdin for Teams and Organizations</a></li>
<li><a class="post-section-overview" href="#heading-how-to-invite-project-members-and-contributors">How to Invite Project Members and Contributors</a></li>
<li><a class="post-section-overview" href="#heading-project-roles">Project Roles</a></li>
<li><a class="post-section-overview" href="#heading-how-to-assign-or-change-roles">How to Assign or Change Roles</a></li>
<li><a class="post-section-overview" href="#heading-project-managers">Project Managers</a></li>
<li><a class="post-section-overview" href="#heading-tasks">Tasks</a></li>
<li><a class="post-section-overview" href="#heading-project-reports">Project Reports</a></li>
<li><a class="post-section-overview" href="#heading-conversations-on-crowdin">Conversations on Crowdin</a></li>
<li><a class="post-section-overview" href="#heading-crowdin-integrations-and-productivity-tools">Crowdin Integrations and Productivity Tools</a></li>
<li><a class="post-section-overview" href="#heading-how-to-translate-a-website-on-crowdin">How to Translate a Website on Crowdin</a></li>
<li><a class="post-section-overview" href="#heading-freecodecamps-translation-effort">freeCodeCamp's Translation Effort</a></li>
</ul>
<p>Are you ready? Let's begin!</p>
<h2 id="heading-freecodecamp-as-a-real-world-example">🔹 freeCodeCamp as a Real-World Example</h2>
<p>freeCodeCamp.org is a real-world example of an organization and open-source project that has embraced the concept of localization for reaching a global community.</p>
<p>Our coding curriculum is available in many languages, including:</p>
<ul>
<li>English.</li>
<li>Spanish.</li>
<li>Chinese.</li>
<li>Italian.</li>
<li>Portuguese.</li>
<li>Ukrainian.</li>
<li>Japanese.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/freecodecamp-language-dropdown-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>How to Choose a Language on freeCodeCamp.</em></p>
<p>Our community is actively working on translating freeCodeCamp into many world languages, including:</p>
<ul>
<li>Arabic.</li>
<li>Azerbaijani.</li>
<li>Bengali.</li>
<li>Chinese Simplified.</li>
<li>Dutch.</li>
<li>French.</li>
<li>German.</li>
<li>Hebrew.</li>
<li>Hindi.</li>
<li>Indonesian.</li>
<li>Italian.</li>
<li>Japanese.</li>
<li>Korean.</li>
<li>Nepali.</li>
<li>Persian.</li>
<li>Portuguese.</li>
<li>Romanian.</li>
<li>Spanish.</li>
<li>Swahili.</li>
<li>Turkish.</li>
<li>Ukrainian.</li>
<li>Urdu, and more.</li>
</ul>
<p>We have many world languages available for localization and we also run localized publications, YouTube channels, forums, and so on.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/freecodecamp-crowdin-project.png" alt="Image" width="600" height="400" loading="lazy">
<em>Coding Curriculum localization project and available languages.</em></p>
<h2 id="heading-a-localization-effort-by-humans-for-humans">🔹 A Localization Effort by Humans, for Humans</h2>
<p>Our localization process is focused on what matters the most: our amazing community of learners who wake up every day excited about learning new skills.</p>
<p>We believe that language and culture should not be barriers to learning. Knowledge should be accessible worldwide.</p>
<p>This is why we started this process and why we'll continue our localization efforts until we reach our goal of guaranteeing access to knowledge around the world.</p>
<p>One of the key aspects of our localization process is that it is managed and run by humans, for humans. Translations are written and approved by members of our amazing community and staff.</p>
<p>Let's be honest, anyone can tell when a translation has been generated automatically. It's much more literal, it lacks the clarity, and it feels disconnected from the context and from the original tone of the text.</p>
<p>Human translators are much better at adapting languages, and translating sentences in a way that sounds more natural in different languages and cultures.</p>
<p>At freeCodeCamp, we have an amazing community of contributors who dedicate their time to translate our content and an amazing team of staff members who oversee the process with the ultimate goal of publishing high-quality translations for our learners.</p>
<p>Since we launched our localization effort, more than 2,000 translators and over 60 proofreaders have helped us accomplish our mission.</p>
<p>💡 <strong>Tip:</strong> If this sounds interesting to you and you would like to join freeCodeCamp's translation effort, please read our <a target="_blank" href="https://contribute.freecodecamp.org/#/index">contributing guidelines</a>. At the end of this article, you will find more information on our localization effort.</p>
<p>Managing such a large project with a worldwide community of contributors might seem complicated, right? How can we accomplish all of this as a non-profit organization?</p>
<p>You will get answers to those questions in this book.</p>
<p>We will cover all the fundamentals of localization, and the basic and advanced features of <a target="_blank" href="https://crowdin.com/">Crowdin</a>.</p>
<p>Are you ready? Let's begin.</p>
<h2 id="heading-what-are-the-fundamentals-of-localization">🔹 What are the <strong>Fundamentals</strong> of <strong>Localization?</strong></h2>
<p>We will start with an overview of the fundamentals of the localization process and the steps that you'll need to take to make sure that your product can be used without any language or cultural barriers.</p>
<h3 id="heading-what-is-localization">What is Localization?</h3>
<p>First of all, let's define <strong>localization</strong>.</p>
<p>According to the <a target="_blank" href="https://dictionary.cambridge.org/dictionary/english/localization">Cambridge Dictionary</a>, localization is defined as:</p>
<blockquote>
<p>The process of organizing a business or industry so that its main activities happen in local areas rather than nationally or internationally.</p>
</blockquote>
<p>In the context of products and services, localization basically means adapting them to the language and culture of a specific population. This also applies to software products because they need to be adapted to different cultures as well.</p>
<h3 id="heading-translation-vs-localization">Translation vs Localization</h3>
<p>You may be surprised to know that the concept of localization is different from the concept of translation. It's actually broader.</p>
<p>The <a target="_blank" href="https://dictionary.cambridge.org/dictionary/english/translation">Cambridge Dictionary</a> defines translation as:</p>
<blockquote>
<p>The activity or process of changing the words of one language into the words in another language that have the same meaning.</p>
</blockquote>
<p>Notice the key part of this definition: "changing the words to keep the same meaning."</p>
<p>Translation involves changing the words of a language into another language to keep their original meaning. It is very helpful but a bit limited because its goal is to say exactly the same thing in a different language.</p>
<p>However, localization can go beyond that to adapt the content better to another culture or country. </p>
<p>For example, localization is particularly helpful for marketing campaigns and ads that try to reach audiences and convince them to purchase their products. Certain cultures may accept certain colors better, or they may have local phrases or slangs that the local population is more familiar with.</p>
<p>In this case, localizing the campaign is better than writing a literal word-for-word translation.</p>
<p><strong>Continuous localization</strong> takes this concept one step further. It involves localizing a product continuously as it is updated or expanded in an agile product development cycle. It is often used to localize software products.</p>
<h2 id="heading-importance-of-localization">Importance of Localization</h2>
<p>Why should you localize your product or platform? Well, the world is very diverse, and different cultures have their distinctive customs and speak different languages. </p>
<p>Did you know that, according to the <a target="_blank" href="https://www.linguisticsociety.org/content/how-many-languages-are-there-world">Linguistic Society of America</a>, there are more than 6,000 languages in the world?</p>
<p>Among the top 20 most widely spoken languages in the world, we can find these:</p>
<ul>
<li>English.</li>
<li>Mandarin Chinese.</li>
<li>Hindi.</li>
<li>Spanish.</li>
<li>French.</li>
<li>Arabic.</li>
<li>Bengali.</li>
<li>Portuguese.</li>
<li>Urdu.</li>
<li>German.</li>
<li>Japanese.</li>
</ul>
<p>💡 <strong>Tip:</strong> You can find more information on languages by total number of speakers in <a target="_blank" href="https://en.wikipedia.org/wiki/List_of_languages_by_total_number_of_speakers">this article</a>.</p>
<p>A large proportion of the world's population is not bilingual. Not everyone around the world has the opportunity to learn and master English as a second language but every single person around the world is a potential user of your product or platform. </p>
<p>That is why localization can be so important for you.</p>
<p>For example, if you are creating an educational platform, you will be able to reach people and accomplish your mission at a global scale by localizing your website and content.</p>
<p>If you are building a commercial product or platform, every single person around the world can be a potential user. </p>
<p>Don't let language become a barrier to reach your users. Localization can be your best ally. </p>
<h2 id="heading-localization-terminologies">Localization Terminologies</h2>
<p>Now that you know why localization is so important, let's dive into some important terminologies that you'll come across very often in the context of translation and localization.</p>
<h3 id="heading-internationalization">Internationalization</h3>
<blockquote>
<p>The action of becoming or making something become international.<br>— <a target="_blank" href="https://dictionary.cambridge.org/dictionary/english/internationalization">Cambridge Dictionary</a>.</p>
</blockquote>
<p>In the context of localization for a software product, it also involves adapting the user interface for working with other languages and making sure that it is ready to be translated.</p>
<h3 id="heading-culturalized">Culturalized</h3>
<blockquote>
<p>Deriving from or imposed or conditioned by culture.<br>— <a target="_blank" href="https://www.merriam-webster.com/dictionary/culturalized">Merriam-Webster Dictionary</a>.</p>
</blockquote>
<p>Every culture has different traditions and vocabulary. Culture can play a key role in how communities embrace products, campaigns, and platforms. Understanding how to adapt them is very important to succeed.</p>
<h3 id="heading-pseudolocalization">Pseudolocalization</h3>
<p>The <em>pseudo</em> prefix is defined as:</p>
<blockquote>
<p>Pretended and not real.<br>— <a target="_blank" href="https://dictionary.cambridge.org/dictionary/english/pseudo">Cambridge Dictionary</a>.</p>
</blockquote>
<p>That is exactly what pseudolocalization is all about. It is a process creating fake translations that act as placeholders for the real translations in a platform or product.</p>
<p>You may ask: "Why would we ever need to use fake translations?"</p>
<p>The answer is that we use them to check if our software is ready to handle multiple languages even before the translation process begins.</p>
<p>Checking if a language that tends to have longer or shorter words works well with our current user interface and checking if right-to-left languages are displayed correctly are common use cases.</p>
<p>This process is also helpful to find any strings that may still be hard-coded in the project source files. You may need to move them to the resources file where you keep all your project strings.</p>
<p>That is the main purpose of pseudolocalization: checking if everything is ready to start translating.</p>
<h3 id="heading-machine-translation-mt">Machine Translation (MT)</h3>
<blockquote>
<p>The process of using artificial intelligence to automatically translate text from one language to another without human involvement.<br>— <a target="_blank" href="https://aws.amazon.com/what-is/machine-translation/">Amazon Web Services</a>.</p>
</blockquote>
<p>We will talk about this term in more detail because the localization management platform that we will use to translate our resources has this feature, and it can save us a lot time. </p>
<h3 id="heading-translation-memory-tm">Translation Memory (TM)</h3>
<blockquote>
<p>A database that stores "segments", which can be sentences, paragraphs or sentence-like units (headings, titles or elements in a list) that have previously been translated, in order to aid human translators.<br>— <a target="_blank" href="https://en.wikipedia.org/wiki/Translation_memory">Wikipedia</a>.</p>
</blockquote>
<p>With this feature, you can save previous translations and "reuse" them to save time.</p>
<p>💡 <strong>Tip:</strong> Note that the acronyms (MT and TM) are very similar and but they are different. Please take a moment to understand the differences between these two concepts because you'll see them in this book frequently.</p>
<h3 id="heading-large-language-models-llms">Large Language Models (LLMs)</h3>
<blockquote>
<p>Deep learning algorithms that can recognize, summarize, translate, predict, and generate content using very large datasets.<br>— <a target="_blank" href="https://www.nvidia.com/en-us/glossary/data-science/large-language-models/">Nvidia</a>.</p>
</blockquote>
<p>These terms are fundamental if you are looking to dive into translation and localization.</p>
<p>You may also find words that use numbers to represent abbreviations. They are called numeronyms.</p>
<ul>
<li><strong>L10n</strong>: this numeronym stands for Localization. The number 10 stands for the 10 letters between the <strong>l</strong> at the start and the <strong>n</strong> at the end.</li>
<li><strong>i18n</strong>: this numeronym stands for Internationalization (yes, it's a very long word!). The number 18 stands for the 18 letters between the <strong>i</strong> at the start and the <strong>n</strong> at the end.</li>
</ul>
<p>💡 <strong>Tip:</strong> Sometimes, you may find L10n with the L capitalized or you may find it in lowercase, like this: l10n. Capitalizing the L is helpful to distinguish it from the i in the i18n numeronym (they can look very similar in certain types of fonts).</p>
<h2 id="heading-translation-vs-proofreading">Translation vs Proofreading</h2>
<p>Another important aspect that you should also know is the difference between translating and proofreading. </p>
<p><strong>Translation</strong> involves changing the words from one language to another with the goal of keeping the same meaning.</p>
<p>But after translators have completed their work, the localization team will also need to review, edit, and approve the translations to make sure that everything is accurate and correct. This process of checking the translations is called <strong>proofreading</strong>.</p>
<p>Translating and proofreading are different stages of the localization process. We'll look these processes in more detail, and you will learn the steps involved and the role of team members in making sure that the content is localized correctly.</p>
<h2 id="heading-what-types-of-resources-can-be-localized">What Types of Resources Can Be Localized?</h2>
<p>When we talk about translation and localization, the first thing that comes to mind is translating files with text, right?</p>
<p>But this is not the only type of resource that we can localize. We can localize documents, spreadsheets, websites, games, dialogues, scripts, audio, video, graphics, and so on.</p>
<p>Think about podcasts and videos. They can be localized with voiceovers. We just need to translate their transcripts, replace the original audio and synchronize the translated narration.</p>
<p>Captions and subtitles can also be localized. This is a form of text too but it comes from a video source. You can see how different types of files can be closely related in the localization process.</p>
<p>Finally, we can localize graphics such as image files, visual marketing campaigns, ads, and more. </p>
<p>The main point to highlight here is that localization and translation are not limited to written resources. There are wide variety of resources that we can localize to reach a wider audience. </p>
<h2 id="heading-common-file-formats">Common File Formats</h2>
<p>In the last section, we talked about different types of resources that can be translated. Now let's talk about the file formats that you'll usually find in the context of translation. You may also find them in the localization management platform that we will be working on. </p>
<p>💡 <strong>Tip:</strong> Even if you do not use these file formats right now, it's always helpful to understand what they do and what they represent. They may come in handy in the future, or in cases where you find them in the documentation of a localization tool you are using.</p>
<h3 id="heading-comma-separated-values-csv-files">Comma-Separated Values (CSV) Files</h3>
<ul>
<li>File extension: <code>**.csv**</code></li>
<li>This is a text file format in which the values are separated by commas.</li>
<li>Stores tabular data such as numbers and text.</li>
<li>Each line usually represents one record.</li>
<li>Commonly used for data exchange and can be processed using programming languages.</li>
</ul>
<h3 id="heading-html-files">HTML Files</h3>
<ul>
<li>File extension: <code>**.html**</code></li>
<li>HTML stands for HyperText Markup Language.</li>
<li>It is used to represent the structure and content of a website.</li>
<li>If you open this file in a browser, you will see the content of the website.</li>
</ul>
<h3 id="heading-json-files">JSON Files</h3>
<ul>
<li>File extension: <code>**.json**</code></li>
<li>JSON stands for JavaScript Object Notation. </li>
<li>Stores data in a simple plain text format based on key-value pairs.</li>
<li>Used for data exchange, especially across the web because it is lightweight. </li>
</ul>
<h3 id="heading-markdown-files">Markdown Files</h3>
<ul>
<li>File extension: <code>**.md**</code></li>
<li>Used to create formatted text. </li>
<li>It is a lightweight markup language with a specific syntax.</li>
<li>Common applications include writing software documentation, blog posts, and articles.</li>
</ul>
<h3 id="heading-po-portable-object-files">PO (Portable Object) Files</h3>
<ul>
<li>File extension: <code>**.po**</code>.</li>
<li>Used by the <code>**gettext**</code> system, which is commonly used for writing multilingual programs. It is also widely used in the implementation of <code>**GNU gettext**</code>.</li>
<li><code>**gettext**</code> is a standard in many game development engines, like the Unreal Engine. It is used in many programming languages, including C, C++, PHP, and Python.</li>
</ul>
<h3 id="heading-text-file">Text File</h3>
<ul>
<li>File extension: <code>**.txt**</code></li>
<li>Used to store plain text. </li>
<li>It does not contain images or non-text characters.</li>
</ul>
<h3 id="heading-extensible-markup-language-xml">Extensible Markup Language (XML)</h3>
<ul>
<li>File extension: <code>**.xml**</code></li>
<li>Used to store, share, and reconstruct arbitrary data.</li>
<li>Commonly used to exchange data over the internet. </li>
<li>Many localization frameworks use XML. For example, Android uses an XML-based file format to store translatable text.</li>
</ul>
<h3 id="heading-xliff-files">XLIFF Files</h3>
<ul>
<li>File extension: <code>**.xliff**</code></li>
<li>XLIFF stands for XML Localization Interchange File Format.</li>
<li>Uses XML-based format.</li>
<li>Used to standardize the way the localizable data can be passed between localization tools.</li>
</ul>
<h3 id="heading-xlsx-files">XLSX Files</h3>
<ul>
<li>File extension: <code>**.xlsx**</code></li>
<li>Used to store data in spreadsheets.</li>
<li>It is an abbreviation of "Microsoft Excel Spreadsheet".</li>
</ul>
<h3 id="heading-resx-files">RESX Files</h3>
<ul>
<li>File extension: <code>**.resx**</code></li>
<li>Used by .NET applications for storing resources that can be localized.</li>
<li>Uses an XML-based file format.</li>
</ul>
<p>These are the most widely used file formats that you may find in localization projects but there are over hundreds of file formats that you can use.</p>
<p>Crowdin, the localization management platform that we will use on this book, supports more than 100+ file formats.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/supported-formats.png" alt="Image" width="600" height="400" loading="lazy">
<em>Overview of the <a target="_blank" href="https://store.crowdin.com/categories/file-formats">supported formats</a> in Crowdin.</em></p>
<h2 id="heading-localization-phases-and-roles">Localization Phases and Roles</h2>
<p>Awesome. Now that you know more about the types of files that you might find in a localization project, let's take a step further and see this process from a project management perspective.</p>
<p>What steps are required for localizing a project? Where should you start? Here are steps to help you answer those questions:</p>
<h3 id="heading-step-1-define-the-project-scope-and-goals">Step #1 - Define the project scope and goals</h3>
<p>Before you start to localize any file, it's important to take a moment to analyze your project's scope and goals. </p>
<p>Ask yourself:</p>
<ul>
<li>What is your target audience?</li>
<li>What are you trying to achieve by localizing your resources?</li>
<li>How will you achieve those goals?</li>
<li>What parts of your website, game, video, or resource do you need to localize?</li>
<li>Do you need to translate it or localize it (adapt it)? Sometimes, translation can be good enough.</li>
<li>If you need to adapt it to other cultures, how will you achieve this? </li>
<li>Will you seek advice from people who understand these cultures? If yes, how will you contact them?</li>
<li>If you speak other languages, can you translate the resources yourself or do you need to find help based on the complexities of your project? </li>
<li>What is your available budget? </li>
<li>Are your goals realistic given your current budget?</li>
</ul>
<p>You should also determine who is going to translate your resources:</p>
<ul>
<li>Will you be translating the resources yourself?</li>
<li>Will you involve your user-base or community in the translation effort?</li>
<li>Will you hire a team or use the services of a translation vendor? </li>
<li>Will you use automated processes like machine translation to translate or pre-translate resources with artificial intelligence?</li>
</ul>
<p>💡 <strong>Tip:</strong> Crowdin has an option to hire their localization services and services from their partners in the Crowdin Marketplace.</p>
<p>Defining clear and realistic goals can be very helpful for avoiding any unexpected challenges during the process.</p>
<p>Write down your goals and make sure that you have an outline of the steps that you need to take to start, execute, and complete the localization process.</p>
<h3 id="heading-step-2-create-the-source-files-to-be-localized">Step #2 - Create the source files to be localized</h3>
<p>Now that you have clear goals and a clear project scope in mind, having the project source files is a must. These are the files that your localization team will localize.</p>
<p>You should make sure that you have all the necessary source files and resources before you start the localization process. </p>
<p>Of course, you can always add new resources and content later in the process, but having a clear initial idea of the complexities of a project will be helpful later on in terms of the time management and budget required.</p>
<h3 id="heading-step-3-prepare-your-software-for-internationalization">Step #3 - Prepare your Software for Internationalization</h3>
<p>Before the localization process begins, you need to prepare your product for internationalization, which is very technology-specific.</p>
<p>This is especially true for software products. The tools that you use to internationalize a React.js application may be very different from the tools that you use for an Android application, an iOS application, or a game. </p>
<p>However, the approaches and concepts that you will use are essentially the same.</p>
<p>You need to think about how you will adapt your user interface and services to other languages. For example, some languages may have longer or shorter words than the source language and this can change how elements are displayed. </p>
<p>Making sure that everything looks like you intend it to is very important, even before translators and proofreaders get involved in the process.</p>
<p>Another key step is making sure that you have all your translatable text separated from your code. When you translate software, all translatable text is extracted into a resource file that can be shared with translators or uploaded to a localization management platform.</p>
<p>The Crowdin team recommends storing larger files, such as HTML pages, and email templates, in a separate directory and keeping one directory per target locale. They suggest that "if you are translating your content into 5 target languages, you would have 5 copies of your resource files with "UI labels" and 5 directories with all other assets like HTML files."</p>
<p>If you are developing a web application, you will also need to implement multilingual routing. Your application should allow users to select their preferred language. </p>
<p>To do this, you have two options. You can:</p>
<ul>
<li>Add the language code as part of the domain name. For example: <code>**fr.example.com**</code>.</li>
<li>Add the language code to the URL. For example: <strong><code>example.com/fr</code></strong>. </li>
</ul>
<p>This is recommended for Search Engine Optimization (SEO) purposes.</p>
<p>Your software should also be able to handle and display adapted numbers, dates, and currencies since localization may also involve adapting them to different formats for different cultures.</p>
<p>Context will also be very important. Many internationalization tools create resource files with only one key-value pair for each piece of text. They associate each piece of text in the source language with its corresponding translation.</p>
<p>But it is very important to make sure that the resource files of your project also include some contextual information of the content or elements around them. This can be very helpful for translators because they can choose the best translations possible based on the context around the string.</p>
<p>Finally, your application should also be able to handle pluralization correctly because different languages may have different plural forms. </p>
<p>💡 <strong>Tip:</strong> Some of these features may be available with the software development kit (SDK) that you are using, but you may need to add some of them using third-party libraries. It's always important to consider and check this.</p>
<h3 id="heading-step-4-assemble-a-team">Step #4 - Assemble a Team</h3>
<p>If you analyze the scope of the project and decide that you cannot complete it by yourself, then it's time to assemble a team.</p>
<p>You may hire a team or, if you are a non-profit organization like freeCodeCamp, use crowdsourcing to ask your community for help with the translations. You may be surprised by the number of generous and kind members of your community who will be willing to help you achieve your goals.</p>
<p>Once you have your team, you can assign them roles:</p>
<ul>
<li><strong>Translators</strong> use the localization management platform you choose to translate the resources. </li>
<li><strong>Proofreaders</strong> review, edit, and approve the translations. It's always helpful to review the translations to fix any typos or inconsistencies.</li>
<li><strong>Developers</strong> work on integrating the tools you choose to automate the localization process.</li>
<li><strong>Project Managers</strong> coordinate the tasks of the project. They assign translators and proofreaders to specific tasks to make sure that the project moves forward as fast as possible. </li>
</ul>
<h3 id="heading-step-5-choose-the-localization-tools">Step #5 - Choose the Localization Tools</h3>
<p>Choosing the right localization tool can be essential for reaching your goals. In the world of localization, there is a tool called Translation Management System (TMS).</p>
<p>This type of system is designed to help you automate repetitive tasks with the goal of optimizing your team's workflow. Humans will still have a role to play in the localization process, but with the help of a translation management system, they can achieve their goals much faster. </p>
<p>Usually, these systems can be integrated with content management systems (CMS) to import content automatically from other platforms, such as blogging platforms. Once it is imported, you can localize it and export it in order to publish the translated versions.</p>
<p>With the proper integrations, translation management systems can also check if there have been changes in the source files and import the new content automatically to start localizing it. </p>
<p>A real-world example of this process is right next to us — freeCodeCamp translates its source files in Crowdin. When a file from freeCodeCamp's curriculum changes, the new content is updated automatically in the system, so contributors can translate it and publish it very quickly. </p>
<p>Automating this process can be very helpful, especially for large organizations with different projects and files, so you do not have to keep track of these changes manually. </p>
<h3 id="heading-step-6-translate-the-resources">Step #6 - Translate the Resources</h3>
<p>If you already chose a translation management system or another helpful tool, then it's time to start translating the resources.</p>
<p>Usually, these platforms will divide the source content into what they call "strings", which are parts of the original text that you can translate. Translators will translate the strings and save their translations. </p>
<p>The software will take care of storing and combining the strings to replace them in the correct place in your file. </p>
<h3 id="heading-step-7-proofread-the-translations">Step #7 - Proofread the Translations</h3>
<p>Proofreading is one of the most important parts of the process because it's like the last quality assurance step made by humans. </p>
<p>Proofreaders should check if the translations are accurate, and if there is a better way to adapt them to the culture or language. They can also check if there are typos or misspelled words, and if the correct format is used. They can edit and approve the translated strings.</p>
<p>Sometimes they may find an extra comma, a missing emoji, an extra space, or a missing letter and those small details really count for the user experience, so this step should be taken very seriously. </p>
<h3 id="heading-step-8-export-the-localized-resources">Step #8 - Export the Localized Resources</h3>
<p>After proofreading and approving all the translations, the next thing to do is to export the final localized resources.</p>
<p>If your project is small, you may choose to do this manually. But if your project is more complex, you may choose to automate this process with different integrations on your localization management system.</p>
<p>For example, Crowdin has integrations with different platforms, including GitHub, Google Drive, Google Sheets, Dropbox, MailChimp, and so on.</p>
<p>If your translations are ready and approved and you set up a GitHub integration, the translated files will be updated automatically in your project's repository. You can even configure where the translated files will be stored.</p>
<h3 id="heading-step-9-check-for-changes">Step #9 - Check for Changes</h3>
<p>Projects and platforms can evolve over time. Files can change as you add new features and content. This is especially true for freeCodeCamp since we add new content and update our existing content on a regular basis. </p>
<p>So how can we handle these changes and still keep our platform properly localized?</p>
<p>Thanks to Crowdin, we can use integrations to be notified of the changes made to files and we can know if we have new strings to be translated. </p>
<p>When this happens, our amazing team of contributors and staff members will start translating and proofreading the new strings, repeating this cycle every time we need to bring the translation percentage back to 100%.</p>
<h2 id="heading-crowdin-fundamentals-for-localization-projects">🔹 <strong>Crowdin Fundamentals for Localization Projects</strong></h2>
<p>Now that we covered the fundamental concepts of localization, we'll use them in the localization management platform that powers freeCodeCamp's localization effort.</p>
<h3 id="heading-what-is-a-localization-management-platform">What is a Localization Management Platform?</h3>
<p>This is a platform that helps you and your team to localize your resources, products, and platforms efficiently through automation, cloud-based services, and integrations with other platforms.</p>
<p>We talked about translation management platforms before, right?</p>
<p>Localization management platforms are very similar but they help you to localize your products, which is even broader than just translating the text word by word. </p>
<h3 id="heading-what-is-crowdin">What is Crowdin?</h3>
<p>Crowdin is a localization management platform that can be described as:</p>
<blockquote>
<p>A cloud-based solution that streamlines localization management for your team. (<a target="_blank" href="https://crowdin.com/">Source: Crowdin</a>)</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/crowdin-landing-page.png" alt="Image" width="600" height="400" loading="lazy">
<em>Crowdin's landing page.</em></p>
<p>The team mentions that, "It's the perfect place to effectively manage all of your multilingual content. It allows you to streamline the localization process and keep your workflow agile."</p>
<p>This platform is also great for teams and organizations who are planning to localize their content into multiple languages.</p>
<p>This is <a target="_blank" href="https://crowdin.com/">Crowdin's official website</a> in case you would like to check it out:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://crowdin.com/">https://crowdin.com/</a></div>
<p>You will be applying your knowledge of localization on this platform, and you'll even learn how to localize a website in just a few minutes with Crowdin's services and integrations. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/crowdin-workflow.png" alt="Image" width="600" height="400" loading="lazy">
<em>Crowdin Workflow. Image taken from Crowdin's <a target="_blank" href="https://crowdin.com/">official website</a>.</em></p>
<h3 id="heading-the-founder-of-crowdin">The Founder of Crowdin</h3>
<p><a target="_blank" href="https://crowdin.com/page/about-crowdin">Serhiy Dmytryshyn</a> is the founder and CEO of Crowdin. He launched the company in 2009 and it now has over 2 million registered users in over 160 countries.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Founder-and-CEO-of-Crowdin.png" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://crowdin.com/page/about-crowdin">Serhiy Dmytryshyn</a>, founder and CEO of Crowdin.</em></p>
<p>We had the opportunity to meet with him and ask him how he would describe Crowdin in five words. His answer was:</p>
<blockquote>
<p>Continuous Localization for Modern Companies.<br>— Serhiy Dmytryshyn</p>
</blockquote>
<p>His vision is for Crowdin to be the best platform for localizing products that are constantly evolving and for projects that may never have a final version because they will be continuously improved, expanded and updated, such as software products.</p>
<p>freeCodeCamp is an example of this. We are constantly adding and updating our content, which means that we also need an efficient and agile localization process to keep our platform accessible and updated for our global community.</p>
<p>The <a target="_blank" href="https://crowdin.com/page/about-crowdin">main goal</a> of Crowdin is to:</p>
<blockquote>
<p>Expand the potential of agile localization.</p>
</blockquote>
<p>But what is agile localization? Let's see.</p>
<h3 id="heading-what-is-agile-localization">What is Agile Localization?</h3>
<p>Agile localization is a process in which localization is incorporated into an agile product development cycle, with the goal of localizing the product as quickly as possible as it evolves.</p>
<p><strong>💡 Tip:</strong> An agile product development cycle is a cycle in which a product is constantly being updated in an iterative approach.</p>
<p>An agile localization process differs from the traditional localization process in that the translations are not only written once and then added to the final product. They are continuously added and updated as the product changes.</p>
<p>This sound great, right?</p>
<p>But constant updates also require constant management, team work, file uploads and downloads, platform deployments, and so on. </p>
<p>This process could become complicated very quickly if your team does not have the right tools, but with a localization management platform like Crowdin, you and your team can save time and accomplish your goals more efficiently.</p>
<h3 id="heading-advantages-of-crowdin">Advantages of Crowdin</h3>
<p>Let's see some of the reasons why you should use Crowdin:</p>
<ul>
<li>You can connect your project with external services through integrations to automate part of the localization process.</li>
<li>You can store your translations on their cloud-based services and grant access to team members and contributors from all around the world. </li>
<li>You can generate machine translations automatically when a resource is created and ask translators to check and edit them to save time.</li>
<li>Your team can check the quality and format of the translations with Crowdin's quality assurance, spellchecking, and proofreading features.</li>
<li>You can generate reports, communicate with team members internally, assign roles and permissions, invite new members, and much more.</li>
</ul>
<p>Basically, it's a platform that will make the localization process much easier for you and your team.</p>
<h3 id="heading-crowdins-free-plan">Crowdin's Free Plan</h3>
<p>One great thing about Crowdin is that they offer a completely free plan with all the essential features for translators to start localizing their content.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/crowdin-free-plan.png" alt="Image" width="600" height="400" loading="lazy">
<em>Crowdin's free features.</em></p>
<p>Yes, it's free! You only need to create an account and you will be able to: </p>
<ul>
<li>Create unlimited public projects that everyone can see and contribute to. </li>
<li>Add unlimited translators to your public projects.</li>
<li>Create one private project.</li>
<li>Host up to 60,000 words in your translations. </li>
<li>Use helpful features for improving translators' efficiency. </li>
<li>Add one integration to your project (we will talk about integrations in just a moment). </li>
</ul>
<p>When you sign up and create your account, you can also start a 14-day free trial of their Team plan and they also have a 30-day trial period for their Business plan.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/free-trial.png" alt="Image" width="600" height="400" loading="lazy">
<em>Frequently Asked Question (FAQ).</em></p>
<p>Crowdin also has <a target="_blank" href="https://crowdin.com/pricing#annual">other plans</a> to fit your needs. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/crowdin-pricing.png" alt="Image" width="600" height="400" loading="lazy">
<em>The plans that you can choose from.</em></p>
<h3 id="heading-crowdin-for-open-source-projects-and-educational-institutions">Crowdin for Open-Source Projects and Educational Institutions</h3>
<p>As a non-profit organization, freeCodeCamp has a special license that Crowdin grants to open-source projects and educational institutions to support their mission.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/crowdin-for-nonprofits.png" alt="Image" width="600" height="400" loading="lazy">
<em>Frequently Asked Question (FAQ).</em></p>
<p>If you represent an open source project or an educational institution, you can contact Crowdin for an <a target="_blank" href="https://crowdin.com/page/open-source-project-setup-request">Open Source Request</a> or an <a target="_blank" href="https://crowdin.com/page/academic-license-project-setup-request">Academic License Request</a>. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/crowdin-for-open-source.png" alt="Image" width="600" height="400" loading="lazy">
<em>Crowdin for Open Source.</em></p>
<p>The Crowdin team will assist you and your organization.</p>
<h2 id="heading-important-terminologies-for-using-crowdin">Important Terminologies for Using Crowdin</h2>
<p>Before we dive into practicing with the features of Crowdin, let's talk a little bit about important terminologies for working with localization management platforms.</p>
<p>You will find these terms very often in the sections that follow, so let's talk about them in detail. </p>
<h3 id="heading-strings">Strings</h3>
<p>When you upload a resource to Crowdin, the platform has to divide the text into smaller "segments" that can be translated and saved individually until all the translations are ready. These segments of the original text are what we call "strings". After they have been translated and approved, they cab be combined to generate the localized version of the resource. </p>
<p><strong>💡 Tip:</strong> You can think of strings as the smallest units of the translation process. We do not translate the text word by word. We translate them string by string.</p>
<h3 id="heading-source-language">Source language</h3>
<p>The source language is the original language of the resource. For example, freeCodeCamp's source language is English since the curriculum and documentation are created in English. </p>
<h3 id="heading-target-language">Target language</h3>
<p>This is the language that our resources are translated into. For example, freeCodeCamp's projects has different target languages because we translate our resources into different languages.</p>
<h3 id="heading-translation-memory-tm-1">Translation Memory (TM)</h3>
<p>This is like a database where we store all the previously translated "segments" of our project. We may store sentences, paragraphs, or other units of the text with their matching source segments. The goal is to reuse the same translations later on in projects when we find them. It is a feature that can save you a lot of time because it only takes a few seconds to choose a saved translation. We can adapt them if we need to but we'll still have a foundation to work on.</p>
<h3 id="heading-machine-translation-mt-1">Machine Translation (MT)</h3>
<p>This process involves a computer software translating the resources of your project automatically without any human intervention. Usually, artificial intelligence and machine learning are part of this process. Translators and proofreaders can then take the computer-generated translations and adapt them or fix them as needed.</p>
<p>💡 <strong>Tip:</strong> Please note that translation memory (TM) and machine translation (MT) are very different even thought their acronyms are very similar. This may be a bit confusing at first, but always remember that "memory" refers to a translation's database and "machine" refers to an automated translation process. </p>
<h3 id="heading-qa-checks">QA Checks</h3>
<p>QA means "Quality Assurance". This is the process of checking if the translations have the correct format and spelling. Crowdin has many QA features that can help your team find and fix any potential errors.</p>
<h3 id="heading-glossary">Glossary</h3>
<p>This is a database of important terms in your project with their corresponding meanings. The goal of creating and maintaining a glossary is to give your translators more context about the terms and help them choose the most accurate translations. </p>
<h3 id="heading-screenshot">Screenshot</h3>
<p>A picture of what you can see on your computer screen at a particular moment. This is stored as an image file.</p>
<h3 id="heading-crowdsourcing">Crowdsourcing</h3>
<p>This is a localization practice based on community cooperation. Basically, if you are an organization and your goal is to translate your resources into many languages, you can ask help from your community. freeCodeCamp's translation effort is an example of crowdsourcing.</p>
<h3 id="heading-pre-translation">Pre-translation</h3>
<p>This is an automated technique that you can use in Crowdin to pre-translate your project automatically using either Machine Translation (MT) or Translation Memory (TM). Then, your translators can check the computer-generated translations and adapt them as needed.</p>
<h3 id="heading-integrations">Integrations</h3>
<p>These are connections that you can make between Crowdin and other applications or services, such as GitHub, Google Drive, Google Sheets, and so on. This is how freeCodeCamp keeps its GitHub repository translated. When we add new strings, they are automatically uploaded to Crowdin and translators can start working on them.</p>
<h3 id="heading-webhooks">Webhooks</h3>
<p>These are automated "messages" that an application or platform will send to another application or platform when specific events happen. In Crowdin, you can send them when translations are completed, when files are proofread, and so on.</p>
<h3 id="heading-command-line-interface-cli">Command-line Interface (CLI)</h3>
<p>This is a text-based user interface that we can use to interact with a computer program by entering commands. Crowdin has a command-line interface (CLI) called the Crowdin Console Client that allows you to synchronize localization resources with your project.</p>
<h3 id="heading-application-programming-interface-api">Application Programming Interface (API)</h3>
<p>This is an intermediary that allows two applications to communicate with each other by sending information following specific protocols. Crowdin also has an API that can help you to integrate localization into your development process.</p>
<h3 id="heading-custom-variables">Custom Variables</h3>
<p>In Crowdin, you can specify variables that should not be translated. They will be highlighted in the source strings that translators can see. To enable this feature, you will need to contact the support team at Crowdin.</p>
<h2 id="heading-getting-started-with-crowdin">Getting Started with Crowdin</h2>
<p>After this detailed but super important introduction into the fundamentals of localization, now it's time to dive into practice and start working on Crowdin. </p>
<h3 id="heading-how-to-create-a-crowdin-account">How to Create a Crowdin Account</h3>
<p>If your goal is to create a project on Crowdin, you'll need to create an account if you don't have one already.</p>
<p>To do that, go to <a target="_blank" href="https://crowdin.com/">crowdin.com</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/crowdin-landing-page-signed-out.png" alt="Image" width="600" height="400" loading="lazy">
<em>Crowdin Landing page.</em></p>
<p>Click on Sign up.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/sign-up.png" alt="Image" width="600" height="400" loading="lazy">
<em>Sign up Button.</em></p>
<ol start="3">
<li>Create your account by filling and submitting the form. You will need to enter your email, username, and password. You will also have to agree to the terms by checking the checkbox.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/sign-up-form.png" alt="Image" width="600" height="400" loading="lazy">
<em>Sign up form.</em></p>
<p><strong>💡 Tip:</strong> After signing up, you will need to confirm your email address. You will receive an email from Crowdin with a link that you can click on to go to your profile. You should see a confirmation message saying that your email was confirmed.</p>
<p>After signing up (or logging in if you already have an account), you will see your new Crowdin profile where you can manage your projects, team members, workflows, activity, and so on.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/new-profile.png" alt="Image" width="600" height="400" loading="lazy">
<em>New Crowdin Profile.</em></p>
<p>🎉 Congratulations! Now you have your Crowdin account and you are ready to start customizing your profile. </p>
<h3 id="heading-how-to-customize-your-crowdin-profile">How to Customize your Crowdin Profile</h3>
<p>To customize your profile:</p>
<p>Click on the small profile image at the top right, and choose "Settings" from the dropdown menu.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/settings-menu.png" alt="Image" width="600" height="400" loading="lazy">
<em>Customize your profile.</em></p>
<p>You will see your profile and the information that you can customize, such as your:</p>
<ul>
<li>Profile image.</li>
<li>Full name, username, and email.</li>
<li>Company and job title.</li>
<li>Gender.</li>
<li>A brief description of you.</li>
<li>Language, timezone, and time format.</li>
<li>Preferred languages.</li>
<li>Appearance (light, dark, or based on your local time).</li>
<li>Privacy. By default, your profile is public. Check this option if you would like to make your profile private.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/black-profile-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Account Settings &gt; Profile.</em></p>
<p>💡 <strong>Tip:</strong> From this page, you can also delete your account. You will see a red button at the bottom and a warning of the consequences of doing so. You should only click this button if you are absolutely sure that you need to delete all your projects and the data associated with them.</p>
<h3 id="heading-how-to-create-a-project-on-crowdin">How to Create a Project on Crowdin</h3>
<p>Now that you know how to customize your profile, let's create a project. You can create a project from your profile page. </p>
<p>If you are in a different part of the platform, you can go back to your profile by clicking on the your small profile image at the top right and click on "Profile", like you can see in the image below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/go-back-to-profile.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Profile page.</em></p>
<p>To create a project, click on the "Create Project" button (the green one or the gray one, they are both equivalent).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/create-a-profile.png" alt="Image" width="600" height="400" loading="lazy">
<em>Create Project (green button).</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/create-a-profile-2-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Create Project (gray button).</em></p>
<p>You will see a page where you can fill the basic information about your project, such as:</p>
<ul>
<li>Name.</li>
<li>Project address. This is the URL for your project. If your project address has multiple words, separate them with dashes (-).</li>
<li>Privacy settings (public or private).</li>
<li>The source language.</li>
<li>The target language(s).</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/create-a-project.png" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a Project.</em></p>
<p>💡 <strong>Tip:</strong> Your project address must be unique. It will be filled automatically when you write your project name. If it is already taken by another user, you will see a red warning and you will need to choose a different one.</p>
<p>You can choose as many target languages as you need. Just check their checkboxes and they will be added.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/target-languages.png" alt="Image" width="600" height="400" loading="lazy">
<em>Target languages.</em></p>
<p>This what you should see when you start choosing your target languages:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/target-languages-selected.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choosing some target languages.</em></p>
<p>You also have an option to pre-fill the selection with the top 30 languages without selecting them manually:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/select-top-30-languages.png" alt="Image" width="600" height="400" loading="lazy">
<em>Select Top 30 languages.</em></p>
<p>💡 <strong>Tip:</strong> You can also create custom languages or copy the selection that you made for another project.</p>
<p>If you choose to add a custom language, you will see this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/adding-a-custom-language.png" alt="Image" width="600" height="400" loading="lazy">
<em>Adding custom languages.</em></p>
<p>Since this is a completely custom language, you will have to specify:</p>
<ul>
<li>The language name.</li>
<li>If it is a dialect of another language.</li>
<li>The code for that language on Crowdin.</li>
<li>Its three-letter code.</li>
<li>Its locale-code.</li>
<li>If the text will be written from left to right or from right to left. </li>
<li><p>The plural form.</p>
</li>
<li><p>After filling all these information, you are ready to create your project. Just click on the "Create Project" button at the bottom of the page. </p>
</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/create-project.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>💡 <strong>Tip:</strong> You can also click "Cancel" and go back to this page if you want to start over.</p>
<p>Now you should able to see your project. Of course, it will be empty at first but don't worry. We will take care of that in just a moment. 😉</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/project-dashboard.png" alt="Image" width="600" height="400" loading="lazy">
<em>New Project.</em></p>
<h3 id="heading-project-overview">Project Overview</h3>
<p>Let's have a quick tour of the project.</p>
<p>First, you can see the name of the project with its current privacy settings. My demo project is private. You can create unlimited public projects or one private project with your free Crowdin account.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/project-dashboard-name.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Next to the project name, you will see two buttons: "Invite People" and "Buy Translations". </p>
<p>You can invite team members to join your project (we'll cover how to do that in this book) and you can also buy translations from Crowdin.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/project-dashboard-buttons.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can also find all the tabs you need to access the available tools for your project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/project-dashboard-tabs.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You will be in the "Sources" tab by default, where you can see the source files that you have uploaded and the strings of your project. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/project-dashboard-sources.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><strong>💡 Tip:</strong> You will also be able to create folders and add files.</p>
<p>Let's see the other tabs:</p>
<h4 id="heading-dashboard-tab">Dashboard Tab</h4>
<p>This is where you will see a list of the project's target languages.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/dashboard-target-languages.png" alt="Image" width="600" height="400" loading="lazy">
<em>Dashboard tab.</em></p>
<h4 id="heading-translations-tab">Translations Tab</h4>
<p>This is where you can upload existing translations, download your translations as a zip file, target file bundles, and set up over-the-air content delivery.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translations-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>Translations tab.</em></p>
<h4 id="heading-screenshots-tab">Screenshots Tab</h4>
<p>This is where you can upload screenshots of your project to help your translators with more context about the strings they are translating. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/screenshots-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshots tab.</em></p>
<h4 id="heading-tasks-tab">Tasks Tab</h4>
<p>This is where you can create and assign tasks to your team members.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tasks-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>Tasks tab.</em></p>
<h4 id="heading-members-tab">Members Tab</h4>
<p>This is where you can see all the members of your project with their respective roles, when they joined the project, and the actions that you can take for each member.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/members-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>Members tab.</em></p>
<h4 id="heading-integrations-tab">Integrations Tab</h4>
<p>This is where you can add integrations to your project and see all the integrations that your project currently has.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/integrations-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>Integrations tab.</em></p>
<h4 id="heading-reports-tab">Reports Tab</h4>
<p>This is where you can see and generate reports on the activity of your project, including translation and proofreading.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/reports-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>Reports tab.</em></p>
<h4 id="heading-activity-tab">Activity Tab</h4>
<p>This is where you can see the project activity.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/activity-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>Activity tab.</em></p>
<h4 id="heading-discussions-tab">Discussions Tab</h4>
<p>This is where you can open discussion topics to discuss aspects of the project with your team. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/discussions-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>Discussions tab.</em></p>
<h4 id="heading-tools-tab">Tools Tab</h4>
<p>This is where you can find more information on the Command Line Tool, API, Webhooks, and Crowdin in-context (a tool to translate web applications with a real-time preview).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tools-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>Tools tab.</em></p>
<h4 id="heading-settings-tab">Settings Tab</h4>
<p>This is where you can customize the project settings. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/settings-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>Settings tab.</em></p>
<p>Talking about project settings, let's dive into the settings that you can customize for your project.</p>
<h3 id="heading-how-to-customize-your-project-settings-in-crowdin">How to Customize your Project Settings in Crowdin</h3>
<p>You will find different categories of project settings.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/settings-tab-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Settings tab.</em></p>
<h4 id="heading-general-settings">General Settings</h4>
<p>The general settings include:</p>
<ul>
<li>Name.</li>
<li>Public description.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/general-settings-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>General Settings.</em></p>
<ul>
<li>Branding, including a custom domain and a project logo.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/branding-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Branding Settings.</em></p>
<ul>
<li>Badges to show the progress of the localization process.</li>
<li>An option to delete the project.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-18-at-8.25.48-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Badges and Deleting a Project.</em></p>
<h4 id="heading-privacy-and-collaboration">Privacy and Collaboration</h4>
<p>In this category, you will find settings to manage the privacy and notifications of your project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/privacy-and-collaboration.png" alt="Image" width="600" height="400" loading="lazy">
<em>Privacy and Collaboration.</em></p>
<p>You can manage your project's visibility in the project visibility settings. You can set your project to be public or private. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/project-visibility.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Next, we have the privacy settings. You can read a short description of each one of these settings below each corresponding item. To enable a setting, check its checkbox.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/privacy-settings.png" alt="Image" width="600" height="400" loading="lazy">
<em>Default privacy settings. You can customize these to fit your needs.</em></p>
<p>Finally, the notifications settings for translators, project managers, and developers can also be customized. Just check the notifications that you would like to enable.  </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-18-at-8.29.36-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Notifications settings.</em></p>
<h4 id="heading-languages">Languages</h4>
<p>In the languages category, you can change the source and target languages of your project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/languages-settings.png" alt="Image" width="600" height="400" loading="lazy">
<em>Languages settings.</em></p>
<h4 id="heading-quality-assurance-qa-checks">Quality Assurance (QA) Checks</h4>
<p>I promised you that this would be important, right? Here we are. In the quality assurance (QA) category, you can enable QA Checks and choose which specific QA checks you would like to have in your project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/qa-checks.png" alt="Image" width="600" height="400" loading="lazy">
<em>QA Checks category.</em></p>
<p>Crowdin <a target="_blank" href="https://support.crowdin.com/qa-checks/">mentions</a> that:</p>
<blockquote>
<p>The main aim of quality assurance (QA) checks is to help you efficiently handle different language-specific aspects in translations and ensure they are formatted the same way as the source strings and will fit the UI just as well. Some typical QA check issues include missed commas, extra spaces, or typos.  </p>
<p>It’s recommended to review and resolve all QA check issues before building your project and downloading translations.</p>
</blockquote>
<p>These quality assurance checks include:</p>
<ul>
<li>Empty translations.</li>
<li>Length issues.</li>
<li>Tags mismatch.</li>
<li>Spaces mismatch.</li>
<li>Variables mismatch.</li>
<li>Punctuation mismatch.</li>
<li>Character case mismatch.</li>
<li>Special characters mismatch.</li>
<li>"Incorrect translation" issues marked by project members.</li>
<li>Spelling mistakes.</li>
<li>ICU (International Components for Unicode) Syntax Errors.</li>
<li>Consistent terminology that follows the project glossary.</li>
<li>Duplicate translation.</li>
<li>FTL syntax.</li>
<li>Android syntax.</li>
</ul>
<p>After you select the QA Checks that you would like to enable, just click on the "Save" button and your changes will be saved.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/save-qa-checks.png" alt="Image" width="600" height="400" loading="lazy">
<em>Save Button.</em></p>
<h4 id="heading-translation-memories">Translation Memories</h4>
<p>You will also find a category for Translation Memories settings.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-memories.png" alt="Image" width="600" height="400" loading="lazy">
<em>Translation Memories category.</em></p>
<p>We will talk about Translation Memories in detail later on, but know that this is where you can customize all the settings of this helpful feature.</p>
<h4 id="heading-glossaries">Glossaries</h4>
<p>You can also manage your glossaries from the Glossaries category. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/glossaries.png" alt="Image" width="600" height="400" loading="lazy">
<em>Glossaries category.</em></p>
<p>You can check your assigned glossaries and click on links to view the records of each glossary. At the top, you will also find a link to the <a target="_blank" href="https://crowdin.com/store/apps/glossary-translate-app">Translate Glossary App</a>.</p>
<h4 id="heading-import">Import</h4>
<p>In Crowdin, you can import source strings and you can customize settings such as how to handle duplicate strings and how to count the words. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/import-category.png" alt="Image" width="600" height="400" loading="lazy">
<em>Import settings.</em></p>
<h4 id="heading-export">Export</h4>
<p>The export category has helpful settings for exporting your translated files.</p>
<p>You can choose to:</p>
<ul>
<li>Save context information in the files.</li>
<li>Skip untranslated strings.</li>
<li>Skip untranslated files.</li>
<li>Export only approved translations.</li>
<li>Automatically fill in regional dialects.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/export.png" alt="Image" width="600" height="400" loading="lazy">
<em>Export settings.</em></p>
<h4 id="heading-labels">Labels</h4>
<p>Labels can be helpful for adding context to strings and organizing them by topics. They can be useful when you want to search for specific strings. </p>
<p>You can add labels from this category in the settings:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/labels.png" alt="Image" width="600" height="400" loading="lazy">
<em>Labels settings.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/creating-a-label.png" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a New Label.</em></p>
<h4 id="heading-parser-configuration">Parser Configuration</h4>
<p>With the Parser Configuration, you can configure how Crowdin imports and exports selected file types to fit your needs.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/parser-configuration.png" alt="Image" width="600" height="400" loading="lazy">
<em>Parser Configuration category.</em></p>
<h4 id="heading-file-processors">File Processors</h4>
<p>The last group in the settings is File Processors, which allows you to customize how to process supported file formats.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/file-processors.png" alt="Image" width="600" height="400" loading="lazy">
<em>File Processors category.</em></p>
<h2 id="heading-how-to-delete-a-project-in-crowdin">How to Delete a Project in Crowdin</h2>
<p>If you ever need to delete a project, remember that you can do so by going to the "Setting" tab and click on the "General" tab.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/settings-tab-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Settings &gt; General.</em></p>
<p>At the bottom, you will find a red "Delete Project" button. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/delete-a-project-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Delete project.</em></p>
<h2 id="heading-how-to-upload-files-to-your-crowdin-project">How to Upload Files to your Crowdin Project</h2>
<p>Now that you know how to customize your project settings, let's actually add a file to the project. You can either upload your project files manually or automate this process through integrations. </p>
<h3 id="heading-how-to-upload-files-manually">How to Upload Files Manually</h3>
<p>Let's upload a sample PDF file with text and images.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/demo-pdf-document-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Our Demo PDF File. We will translate this in Crowdin.</em></p>
<p>To upload files:</p>
<ol>
<li>Go to your project.</li>
<li>Go to the "Sources" tab. </li>
<li>Click on the green "Add File" button or on the gray "Upload Files" button (please see the screenshot below).</li>
<li>Choose the file that you need to upload from your file system. </li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/upload-files-sources.png" alt="Image" width="600" height="400" loading="lazy">
<em>Upload files or use sample files.</em></p>
<p>💡 <strong>Tip:</strong> To explore how Crowdin works, you can also add Crowdin sample files by clicking on the "Use Samples" button.</p>
<p>After uploading your file, you will see it listed:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/upload-files.png" alt="Image" width="600" height="400" loading="lazy">
<em>Uploading a file.</em></p>
<p>You may need to wait a few seconds before the file is processed. Then, you will see the total string count for your file.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/upload-finished.png" alt="Image" width="600" height="400" loading="lazy">
<em>Upload finished.</em></p>
<p>💡 <strong>Tip:</strong> You can also drag and drop your file into the files area in the "Sources" tab and your file will be uploaded automatically.</p>
<p>If you click on the three small dots on the right, you will see more options for that file, including:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/uploaded-file-options.png" alt="Image" width="600" height="400" loading="lazy">
<em>Additional Options.</em></p>
<ul>
<li>Settings.</li>
<li>Progress.</li>
<li>View strings.</li>
<li>Open in Editor.</li>
<li>Download source.</li>
<li>Rename.</li>
<li>Delete.</li>
</ul>
<h3 id="heading-how-to-upload-files-automatically">How to Upload Files Automatically</h3>
<p>One of the key aspects of Crowdin is how easy it is to connect it to other services through integrations, to automatically upload your files and synchronize your translations. </p>
<p>For example, freeCodeCamp has a GitHub integration set up, so we can automatically synchronize the files of our project when we add new strings that have to be translated on Crowdin.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/github-integration-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>GitHub integration.</em></p>
<p>You can also find hundreds of integrations on the <a target="_blank" href="https://store.crowdin.com/">Crowdin store</a> to connect your project to external services. </p>
<p>Crowdin also has an Application Programming Interface (API) for developers. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/crowdin-api.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Crowdin API <a target="_blank" href="https://developer.crowdin.com/api/v2/">Documentation</a>.</em></p>
<p>The Crowdin team <a target="_blank" href="https://developer.crowdin.com/api/v2/">describes</a> it as:</p>
<blockquote>
<p>A full-featured RESTful API that helps you to integrate localization into your development process. The endpoints that we use allow you to easily make calls to retrieve information and to execute actions needed.</p>
</blockquote>
<p>With this API, you can:</p>
<ul>
<li>Create projects for translation.</li>
<li>Add and update files.</li>
<li>Download translations, and more.</li>
</ul>
<p>It is a great way to automate your localization process. You can learn more about the Crowdin API on the <a target="_blank" href="https://developer.crowdin.com/api/v2/">official documentation</a>.</p>
<p>And the third option to upload files automatically is to use the Command-Line Interface (CLI). </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/crowdin-cli-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Crowdin Command-line Interface (CLI).</em></p>
<p>With this interface, you can:</p>
<ul>
<li>Automate the process of uploading files.</li>
<li>Download translations automatically and save them in the correct locations. </li>
<li>Upload existing translations.</li>
<li>Integrate Crowdin with other tools like Git.</li>
</ul>
<p>To learn more about the Crowdin CLI, check out <a target="_blank" href="https://www.youtube.com/watch?v=0duN4khpWjM">this tutorial</a> created by the Crowdin team.</p>
<p>Now that you know how to upload your files to Crowdin manually and automatically, let's see how you and your team can start translating.</p>
<h2 id="heading-how-to-start-translating">How to Start Translating</h2>
<p>Once your file is uploaded, it's time to start translating. You may start translating it yourself or you ask your team to start working on the translations. </p>
<p>💡 <strong>Tip:</strong> You can assign specific files to your translators and proofreaders with the tasks feature.</p>
<p>Let's assume that you are translating the files yourself. </p>
<p>To start, you need to go to the project's Dashboard tab and select the language that you will be translating your file into from the list of target languages that you chose when you created the project.</p>
<p>I will choose Spanish for this demo.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/list-of-target-languages.png" alt="Image" width="600" height="400" loading="lazy">
<em>Dashboard.</em></p>
<p>You will see all your project files for that specific target language. </p>
<p>On the language page, you can check the translation and proofreading progress of each file, translate and proofread, and upload or download your translations and source files. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/project-files-in-spanish.png" alt="Image" width="600" height="400" loading="lazy">
<em>List of files to be translated into Spanish.</em></p>
<p>You can click on the name of the file that you would like to translate. This will take you to the Translation Editor and you will see your file in the preview.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-editor.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Translation Editor.</em></p>
<p>When upload a file, Crowdin divides it into strings. This process may require certain format conversions based on the type of file that you are uploading.</p>
<p>According to the <a target="_blank" href="https://support.crowdin.com/supported-formats/#converted-file-formats">Crowdin documentation</a>:</p>
<blockquote>
<p>On import, some file formats are automatically converted into other formats to be further parsed and processed.   </p>
<p>You can see the list of the initial file formats and the file formats they’re being converted into in the table below.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/file-formats-table.png" alt="Image" width="600" height="400" loading="lazy">
<em>File formats conversion. Image taken from the <a target="_blank" href="https://support.crowdin.com/supported-formats/#converted-file-formats">Crowdin documentation</a>.</em></p>
<p>We can see that PDF files are converted into DOCX files, the type of file that we usually create in a text editor.</p>
<p>Then, to export the file, <a target="_blank" href="https://support.crowdin.com/supported-formats/#converted-file-formats">Crowdin also mentions</a> that:</p>
<blockquote>
<p>By default, we export the translations in the same format as the source files. For example, if you upload an XML file to Crowdin, you’ll have the XML file exported.</p>
</blockquote>
<h2 id="heading-how-to-use-the-translation-editor">How to Use The Translation Editor</h2>
<p>This is the layout of the translation editor that you will see by default when you click on a file. It is called the Comfortable Mode.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-editor.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Translation Editor.</em></p>
<p>It has four main sections:</p>
<ul>
<li>The left sidebar (in purple below).</li>
<li>Middle-top area (in yellow below).</li>
<li>Middle-bottom area (in orange below).</li>
<li>Right sidebar (in blue below).</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-editor-sections.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Translation Editor in Comfortable Mode.</em></p>
<p>Let's talk about each section.</p>
<h3 id="heading-left-sidebar">Left Sidebar</h3>
<ul>
<li>Highlighted in a purple box in the previous diagram.</li>
<li>Shows you all the strings in your document and a preview of your source file.</li>
<li>You will find helpful tools at the top such as (from left to right): searching strings in the file, changing the view to a list of all the strings, highlighting translated and untranslated strings, showing the translation preview, scale toggle, and adding a string.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/toolbar-options.png" alt="Image" width="600" height="400" loading="lazy">
<em>Left Sidebar - Toolbar at the top.</em></p>
<p>If you click on the first button (from left to right) after the search file field, you can change the view to see a list of all the strings instead of the file preview. </p>
<p>Now you will see a list of all the strings on the left:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/list-of-all-strings.png" alt="Image" width="600" height="400" loading="lazy">
<em>Basic list view.</em></p>
<p>You can always click on this button again to go back to the previous mode, where you can see the strings in the original context and layout of the source file, like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-editor.png" alt="Image" width="600" height="400" loading="lazy">
<em>WYSIWYG ("What You See Is What You Get") Translation Mode.</em></p>
<p>Here, you will see that strings are highlighted in different colors. </p>
<ul>
<li>Red means that the string has not been translated.</li>
<li>Yellow means that the string is partially translated.</li>
<li>Blue means that the string has been translated.</li>
<li>Gray means that the string is hidden and only visible to project managers and proofreaders.</li>
</ul>
<p>When you start proofreading the strings, you will also see:</p>
<ul>
<li>A yellow checkmark if the string is partially approved (if some plural forms are not approved).</li>
<li>A green checkmark if the string has been approved.</li>
</ul>
<p>You may also see a comment icon if a contributor has left a comment on a string or if it has marked the comment as an issue.</p>
<h3 id="heading-middle-top-area">Middle-Top Area</h3>
<ul>
<li>Highlighted in a yellow box in the diagram below. </li>
<li>This is where you can translate a string. You just need to select it from the left sidebar and it will appear in this area. </li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-editor-sections.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Translation Editor in Comfortable Mode.</em></p>
<p>Let's click on a string and see what happens:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/selecting-a-strings.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting a string.</em></p>
<p>Awesome! The string is now selected as the "Source String" and we can start translating it:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/writing-translations.png" alt="Image" width="600" height="400" loading="lazy">
<em>Translate a string.</em></p>
<p>The three tools that you can see at the bottom are (from left to right):</p>
<ul>
<li><strong>Copy Source:</strong> to keep the initial string structure. </li>
<li><strong>Clear:</strong> to erase the translation quickly.</li>
<li><strong>Text Selection Mode:</strong> to copy a part of the translation from Translation Memory (TM) or Machine Translations (MT).</li>
</ul>
<p>If you click on the three dots at the top, you will see additional options for the string, including:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/strings-translation-options.png" alt="Image" width="600" height="400" loading="lazy">
<em>String translation options.</em></p>
<ul>
<li>Hide String.</li>
<li>Copy String URL.</li>
<li>Copy Source Skeleton.</li>
<li>Translation History.</li>
<li>View String in Context.</li>
</ul>
<p>When you write your translation, you will see your translations in the preview. The string will be highlighted in yellow if it is the selected string. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/preview-with-partially-translated-string.png" alt="Image" width="600" height="400" loading="lazy">
<em>Translation in the preview (sidebar). The translated string is in Spanish in the preview.</em></p>
<p>To save your translation, click on the green "Save" button. </p>
<p>After this, you can go to the next string and you will see the previously translated string highlighted in a different color (blue).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translated-saved-string.png" alt="Image" width="600" height="400" loading="lazy">
<em>Saved translation.</em></p>
<p>To go back to the previous string, just click on it or click on the left arrow next to "Source String".</p>
<p>If you go back to the string, you will see something new in the middle-bottom area.</p>
<p>Let's talk about the middle-bottom area.</p>
<h3 id="heading-middle-bottom-area">Middle-Bottom Area</h3>
<ul>
<li>Highlighted in an orange box in the diagram below.</li>
<li>This section has translations made by other contributors (if applicable), translation memory (TM) suggestions, machine translation (MT) suggestions, and translations to other languages.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-editor-sections.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Translation Editor in Comfortable Mode.</em></p>
<p><strong>💡 Tip:</strong> If you click on a suggestion, it will automatically appear in the translation input field.</p>
<p>This is the current state of our project. We have this translated string and you can see the Spanish Translation in the middle-bottom section (orange box below).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/back-to-translated-string.png" alt="Image" width="600" height="400" loading="lazy">
<em>Middle-Bottom Section.</em></p>
<p>For each translation, you will see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/approve-string-translation.png" alt="Image" width="600" height="400" loading="lazy">
<em>Translation.</em></p>
<ul>
<li>The translation in the target language.</li>
<li>The Crowdin user who saved the translation. </li>
<li>When it was saved.</li>
<li>Its current rating (other project members can upvote or downvote a translation).</li>
<li>A checkmark button to approve the translation (like a proofreader).</li>
<li>A trash button to delete the translation.</li>
</ul>
<p>If you are the project owner or you have proofreading permissions, you can approve the string translation yourself. However, it is always recommended to have another team member check your string to avoid any common issues.</p>
<p>To approve the translation, just click on the checkmark button next to the translation. </p>
<p>Now you will see the approved string highlighted in green in the preview:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/approved-string.png" alt="Image" width="600" height="400" loading="lazy">
<em>Approved string highlighted in green.</em></p>
<p>The translated string will now show who approved it and when it was approved:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/back-to-approved-string-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-right-sidebar">Right Sidebar</h3>
<p>And last (but not least!) we have the right sidebar. </p>
<ul>
<li>Highlighted in blue in the diagram below.</li>
<li>This is where you can write comments, search the TM, search for terms on your glossary, add new apps, and find the apps you added through the <a target="_blank" href="https://crowdin.com/store/apps">Crowdin Store</a>.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-editor-sections.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Translation Editor in Comfortable Mode.</em></p>
<p>To write a comment, just go to the comments on the sidebar and write your comment on the text input field at the bottom. You can mark the comment as an issue if you need to.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/writing-a-comment-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Writing a comment.</em></p>
<p>💡 <strong>Tip:</strong> You should write your comment using the source language of the project, so other team members and project managers can understand it.</p>
<p>If you click on the second option on this sidebar, you will be able to search your translation memory for previous translations.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-memory.png" alt="Image" width="600" height="400" loading="lazy">
<em>Search Translation Memory (TM).</em></p>
<p>In the third option, you can search for terms related to the currently selected string in your glossary.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/glossary.png" alt="Image" width="600" height="400" loading="lazy">
<em>Search Terms.</em></p>
<p>What is really great about this search term feature is that, <a target="_blank" href="https://support.crowdin.com/online-editor/#section-4">according to Crowdin</a>:</p>
<blockquote>
<p>If the specific term is not available in the project’s glossary, the system will show you Wikipedia explanations.</p>
</blockquote>
<p>This can be very helpful to understand more about the context of a term when you are translating a resource.</p>
<p>And the last option is a plus icon that will take you to the Crowdin Store, where you can find apps and integrations for your project and you will be able to access them on the sidebar.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/add-apps.png" alt="Image" width="600" height="400" loading="lazy">
<em>Go to the Crowdin Store.</em></p>
<h2 id="heading-translation-editor-modes">Translation Editor Modes</h2>
<p>The translation editor has three modes to customize the layout in a way that fits your needs — Comfortable Mode, Side-by-Side Mode, and Multilingual Mode.</p>
<h3 id="heading-comfortable-mode">Comfortable Mode</h3>
<ul>
<li>Primarily used for translations. </li>
<li>It has the four main sections that we saw in the previous section.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/comfortable-mode.png" alt="Image" width="600" height="400" loading="lazy">
<em>Layout in the Comfortable Mode.</em></p>
<h3 id="heading-how-to-switch-modes">How to Switch Modes</h3>
<p>To switch to another mode, you need to click on the menu icon at the top left of the translation editor:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/change-mode-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Click on this menu icon.</em></p>
<p>Then, click on "View" and choose the mode that you would like to see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/view-change-mode.png" alt="Image" width="600" height="400" loading="lazy">
<em>Change Editor View.</em></p>
<h3 id="heading-side-by-side-mode">Side-by-Side Mode</h3>
<ul>
<li>Primarily used by managers and proofreaders to approve the best translations and by translators to vote translations in a row.</li>
</ul>
<p>The first time you switch to this view, you will see some helpful tips:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tip-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Review or make translations.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tip-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Approve multiple translations at once.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tip-3.png" alt="Image" width="600" height="400" loading="lazy">
<em>Switch to Comfortable view to make new translations.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tip-4.png" alt="Image" width="600" height="400" loading="lazy">
<em>That's all friends!</em></p>
<p>This is what you will see when you enter side-by-side mode. Please take a moment to see it in detail and explore the changes:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/side-by-side-mode.png" alt="Image" width="600" height="400" loading="lazy">
<em>Side-by-Side Mode</em></p>
<p>To see all the possible string status in the side-by-side mode, let's go back to the Comfortable Mode to translate and save another string (but we will not approve the string this time).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/string-translation-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Translating another string.</em></p>
<p>In the side-by-side view, we now have a translated string, an approved string, and strings that we still need to translate.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/side-by-side-with-multiple-strings.png" alt="Image" width="600" height="400" loading="lazy">
<em>Side-by-Side Mode.</em></p>
<p>Let's start with a quick tour. You have four areas that you can resize to fit your needs:</p>
<ul>
<li>At the top left, we find the list of strings. You can select multiple string for bulk operations such as approving multiple strings with just one click.</li>
<li>At the bottom left, we find the preview of the source file. </li>
<li>At the top right, we find the string details.</li>
<li>At the bottom right, we find the current translations and suggestions. This is very similar to what you see in the Comfortable mode.</li>
</ul>
<h4 id="heading-toolbar">Toolbar</h4>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/toolbar.png" alt="Image" width="600" height="400" loading="lazy">
<em>Toolbar.</em></p>
<p>At the top of the list of string, you will see multiple tools, including (from left to right):</p>
<ul>
<li>Search for a string.</li>
<li>Change sorting criteria.</li>
<li>String length in the source file and in the translated version. </li>
<li>Save button. </li>
<li>Cancel button. </li>
<li>Copy source.</li>
<li>Approve string.</li>
<li>Add string.</li>
<li>Edit string.</li>
<li>More options.</li>
</ul>
<p>If you open the "More options" menu by clicking on the three dots, you will see more helpful options for the selected string(s).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/more-options-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>More options.</em></p>
<h4 id="heading-how-to-sort-the-strings">How to Sort the Strings</h4>
<p>You will notice that, by default, the strings will be sorted by their status. </p>
<p><strong>💡 Tip:</strong> Untranslated strings will be displayed first, so you will not see the strings in the order in which they appear in the source file. </p>
<p>You can change the sorting criteria by clicking on the filter icon next to the search field. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/filtering-strings.png" alt="Image" width="600" height="400" loading="lazy">
<em>Filtering the Strings.</em></p>
<p>In this mode, you will also see different visual references of the status of each string. </p>
<p>Here, we can see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/types-of-strings.png" alt="Image" width="600" height="400" loading="lazy">
<em>String status.</em></p>
<ul>
<li>An untranslated string in red.</li>
<li>A translated string in blue. </li>
<li>An approved string with a green checkmark. </li>
<li>A hidden string in gray. </li>
</ul>
<h3 id="heading-multilingual-mode">Multilingual Mode</h3>
<p>Awesome. Now let's go to the multilingual mode. This mode is primarily used by translators and proofreaders to work with multiple languages at the same time.</p>
<p>💡 <strong>Tip:</strong> You can work on up to ten languages simultaneously.</p>
<p>To switch to this mode, click on the main menu icon at the top. Then select "View" and choose "Multilingual".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/multilingual-view.png" alt="Image" width="600" height="400" loading="lazy">
<em>Go to the Multilingual Mode.</em></p>
<p>When you choose "Multilingual", you will need to choose the languages that you are planning to work with.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/languages.png" alt="Image" width="600" height="400" loading="lazy">
<em>Languages for the Multilingual Mode.</em></p>
<p>Let's choose Spanish and Japanese just to see how this mode works. Click on them and then click on the "Apply" button.</p>
<p>You should see this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/multilingual-mode.png" alt="Image" width="600" height="400" loading="lazy">
<em>Multilingual Mode.</em></p>
<p>Each string will have a text field where you can write the translation for each of the target languages selected. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/string-in-multilingual.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>When you are working on the multilingual mode, you can switch between two possible views:</p>
<ul>
<li>List View.</li>
<li>Grid View.</li>
</ul>
<p>This is an example of the list view:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/multilingual-mode.png" alt="Image" width="600" height="400" loading="lazy">
<em>List view in Multilingual Mode.</em></p>
<p>To switch to Grid View, you need to click on the button in the toolbar at the top:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/multilingual-mode-copy.png" alt="Image" width="600" height="400" loading="lazy">
<em>Switch between list and grid view.</em></p>
<p>The other parts of the editor and the tools in this mode are very similar to the Side-by-Side view that you are already familiar with.</p>
<h2 id="heading-how-to-switch-to-another-file">How to Switch to Another File</h2>
<p>You may want to go to another file after translating all the strings in a different file. This is very easy to do.</p>
<p>To do that:</p>
<p>Click on the main menu at the top left.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/main-menu-button.png" alt="Image" width="600" height="400" loading="lazy">
<em>Main Menu.</em></p>
<p>Go to File and then choose "Open...".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/open-another-file-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Open a File.</em></p>
<p>Choose the file that you would like to open and click on "Open" (or double-click on the file name).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/open-file-menu.png" alt="Image" width="600" height="400" loading="lazy">
<em>List of files.</em></p>
<p>💡 <strong>Tip:</strong> You can also get to the list of files much faster by clicking on the file name directly. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/file-click-on-file.png" alt="Image" width="600" height="400" loading="lazy">
<em>Click on the file name.</em></p>
<p>You will be taken to the file you've chosen.</p>
<h3 id="heading-how-to-view-all-strings">How to View All Strings</h3>
<p>If you ever need to see a list of all the strings in a project, you just need to:</p>
<p>Go to the main menu at the top left.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/main-menu-button.png" alt="Image" width="600" height="400" loading="lazy">
<em>Main Menu.</em></p>
<p>Go to "File", and then select "All Strings".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/all-strings-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>See All Strings.</em></p>
<p>You will see a list of all the strings in the project, their status, and translations. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/all-strings-list.png" alt="Image" width="600" height="400" loading="lazy">
<em>All Strings.</em></p>
<h2 id="heading-how-to-translate-rtl-languages">How to Translate RTL Languages</h2>
<p>While some languages like Spanish and Italian are written from left to right (LTR), other languages like Arabic and Urdu are written from right to left (RTL). </p>
<p><a target="_blank" href="https://support.crowdin.com/online-editor/#translating-rtl-languages">Crowdin mentions</a> that:</p>
<blockquote>
<p>When translating between LTR and RTL languages, some elements in the translation field in the Editor might not be displayed the same way as they will be once exported.</p>
</blockquote>
<p>To make sure that the translations will be displayed correctly in the exported file, Crowdin recommends:</p>
<ol>
<li>Clicking the "Copy Source" button when writing the translations. This is the first button on the toolbar.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/toolbar-copy-source-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>The "Copy Source" Button.</em></p>
<ol start="2">
<li><p>Translating the text into your target language.</p>
</li>
<li><p>Leaving any variables or tags exactly the same, even if they do not look the same. They will be in the right position when you export a file.</p>
</li>
</ol>
<p>💡 <strong>Tip:</strong> Crowdin <a target="_blank" href="https://support.crowdin.com/online-editor/#translating-rtl-languages">suggests</a> using the <a target="_blank" href="https://store.crowdin.com/unicode">Unicode Table app</a> to copy and paste right-to-left and left-to-right marks, changing the direction of the text where needed.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-77.png" alt="Image" width="600" height="400" loading="lazy">
<em>Example of translating a RTL language from the <a target="_blank" href="https://support.crowdin.com/online-editor/#translating-rtl-languages">Crowdin documentation</a>.</em></p>
<h3 id="heading-translation-editor-settings">Translation Editor Settings</h3>
<p>You can also customize the settings of the translation editor. </p>
<p>To access these settings, click on the gear icon at the top right of the translation editor.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/editor-settings.png" alt="Image" width="600" height="400" loading="lazy">
<em>Translation Editor Settings.</em></p>
<p>You will see a list of the settings that you can customize.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/editor-settings-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Editor Settings (Part 1)</em></p>
<p>The first part of these settings includes:</p>
<ul>
<li>The minimum match percentage for showing Translation Memory suggestions. </li>
<li>If translations should be checked for quality assurance (QA) issues.</li>
<li>If the editor should auto-complete what you are writing and show you a list of predictions. </li>
<li>If you would like to approve the translations automatically. This can be helpful if you are translating and proofreading the project yourself.</li>
<li>If you would like to move to the next string automatically. </li>
<li>The color theme for the translation editor (light, dark, or automatic).</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/editor-settings-2-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Editor Settings (Part 2).</em></p>
<p>If you scroll down, you will find more settings, such as:</p>
<ul>
<li>If the editor should show only the beginning of the source string in a compact view.</li>
<li>If you would like to show the translation preview for translated strings.</li>
<li>How HTML tags should be displayed. You can show them or hide them. </li>
<li>If non-printable characters should be displayed or not. </li>
<li>If the translation field should be highlighted.</li>
<li>If you would like to enable real-time spellchecking.</li>
<li>The language of the user interface of your translation editor.</li>
</ul>
<p>You can customize these settings to fit your needs.</p>
<h3 id="heading-keyboard-shortcuts">Keyboard Shortcuts</h3>
<p>Another key productivity feature for translators and proofreaders on Crowdin is that they can use keyboard shortcuts.</p>
<p>To see all the keyboard shortcuts available for your operating system, just click on the keyboard icon at the top right.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/keyboard-shortcuts-button-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Open Keyboard Shortcuts.</em></p>
<p>These are the keyboard shortcuts for Windows:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-78.png" alt="Image" width="600" height="400" loading="lazy">
<em>Keyboard Shortcuts (Windows). Screenshot from the <a target="_blank" href="https://support.crowdin.com/online-editor/#helpful-tips">Crowdin Documentation</a>.</em></p>
<p>And these are the keyboard shortcuts for macOS:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/keyboard-shortcuts-macos-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Keyboard Shortcuts (macOS).</em></p>
<p>If you scroll down, you will find more keyboard shortcuts for macOS.</p>
<h2 id="heading-how-to-download-the-translated-files">How to Download the Translated File(s)</h2>
<p>Once your project is translated and approved, you will need to download it. </p>
<p>In Crowdin, you have three different options for downloading files. You can download the entire project, download all the project files in a specific language, or download a specific file in a specific language.</p>
<p>Let's see these options in more detail. </p>
<h3 id="heading-how-to-download-the-entire-project">How to Download the Entire Project</h3>
<p>If you need to download the entire project:</p>
<ol>
<li>Go to your project.</li>
<li>Go to the "Translations" tab. </li>
<li>On "Download as ZIP" section, click on the "Build &amp; Download" button.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/download-project-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Download as ZIP.</em></p>
<p>You will see a progress bar while Crowdin builds the project and then your download will start.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/progress-bar.png" alt="Image" width="600" height="400" loading="lazy">
<em>Build &amp; Download.</em></p>
<p>The ZIP file will have folders for each language. The names of the folders will be their corresponding language codes.</p>
<h3 id="heading-how-to-download-all-files-in-a-target-language">How to Download All Files in a Target Language</h3>
<p>This option is helpful if you need to download all the translated files in a specific target language.</p>
<ol>
<li>Go to your project. </li>
<li>Go to the "Translations" tab.</li>
<li>On "Download as ZIP" section, select the language.</li>
<li>Click on the "Build &amp; Download" button.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/download-language-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Download as ZIP.</em></p>
<h3 id="heading-how-to-download-a-file-in-a-target-language">How to Download a File in a Target Language</h3>
<p>The third option is to download just one file in a specific target language. </p>
<p>To do this:</p>
<ol>
<li>Go to your project.</li>
<li>Go to the Dashboard tab.</li>
<li>Choose the target language. </li>
<li>Click on the file.</li>
<li>Click on the three dots to the right to see the additional options (see the screenshot below).</li>
<li>Click on "Download".</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/download-one-file.png" alt="Image" width="600" height="400" loading="lazy">
<em>Download a File in a Target Language.</em></p>
<p>The download should start and you should have your translated file ready in just a few seconds or minutes.</p>
<p>You can also automate the process of exporting or downloading your translated files with Crowdin integrations. </p>
<h2 id="heading-how-to-use-translation-memory-tm"><strong>How to Use Translation Memory (TM)</strong></h2>
<p>Great work so far. Now that you know the basic features of the translation editor, let's talk about more advanced features such as the Translation Memory. </p>
<p>We will see how you can:</p>
<ul>
<li>Create translation memory.</li>
<li>Manage translation memory.</li>
<li>Download and upload translation memory.</li>
<li>Assign translation memory to a project.</li>
</ul>
<p>💡 <strong>Tip:</strong> Remember that TM is like a database of strings that we have translated previously in our project and their corresponding translations. Reusing previous translations can save us a lot of time. </p>
<p>Are you ready? Let's begin. </p>
<h3 id="heading-how-to-create-a-translation-memory-tm">How to Create a Translation Memory (TM)</h3>
<p>To create a TM for your project, you need to:</p>
<ol>
<li>Go to your profile. You can do this by clicking on "Profile" in the dropdown menu that is displayed when you click on your profile image at the top right.</li>
<li>Go to the "Resources" tab.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/resources-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Resource tab in Profile.</em></p>
<ol start="3">
<li>If you already have a project created, you will see a TM for that project. You can also create a new TM, independently from a project (you can assign it to a project later on).</li>
</ol>
<p><a target="_blank" href="https://support.crowdin.com/translation-memory/#creating-tm">Crowdin mentions</a> that:</p>
<blockquote>
<p>Besides the project TMs that are automatically created along the respective projects, you can also create separate TMs, fill them with the appropriate content by uploading your existing TMs in TMX, XLSX, or CSV format, and then assign these TMs to the needed projects.</p>
</blockquote>
<ol start="4">
<li>To create a new TM, click on the green "Create TM" button.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/create-TM-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Create TM.</em></p>
<ol start="5">
<li>Complete the information for your new TM, such as its name, language, and if you would like to assign it to an existing project.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/create-translation-memory.png" alt="Image" width="600" height="400" loading="lazy">
<em>Create Translation Memory.</em></p>
<p>I'm going to create a new TM called "Demo TM" in English. For now, I will not assign it to any project.</p>
<p>Let's see what happens:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/demo-translation-memory.png" alt="Image" width="600" height="400" loading="lazy">
<em>New TM.</em></p>
<p>🎉 Awesome. Now we see the new TM in the list.</p>
<h3 id="heading-how-to-manage-translation-memory-tm">How to Manage Translation Memory (TM)</h3>
<p>If you click on the three dots to the right of the TM to show additional options, you will see the following options:</p>
<ul>
<li>Upload.</li>
<li>Download.</li>
<li>Edit.</li>
<li>View Records.</li>
<li>Delete.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/additional-options-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Additional Options for a Translation Memory.</em></p>
<p>If you select a TM by checking its checkbox, you can delete it, edit it, or view its records. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/manage-tm-2.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Since our new TM is new (and therefore, empty), let's see the records of the TM for our freeCodeCamp Course Project.</p>
<p>If you click on it, you'll see a list of all the records stored in the TM:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-memory-strings-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Translation Memory (TM).</em></p>
<p>From here, you can:</p>
<ul>
<li>Edit the records.</li>
<li>Delete the records.</li>
<li>Search for specific records matching case, whole phrase, and finding an exact match.</li>
<li>Hide or show specific columns.</li>
</ul>
<h3 id="heading-how-to-upload-and-download-translation-memory-tm">How to Upload and Download Translation Memory (TM)</h3>
<p>In the "Resources" tab of your project, you can also upload and download TM.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tm-records-download-upload.png" alt="Image" width="600" height="400" loading="lazy">
<em>Resources toolbar.</em></p>
<p>The file must be in one of the following formats: </p>
<ul>
<li>TMX</li>
<li>XLSX</li>
<li>CSV</li>
</ul>
<p>To upload a TM:</p>
<ul>
<li>Click on the "Upload" button. </li>
<li>Choose your file in your file system. </li>
<li>Match each column to the corresponding language.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tm-records-download-upload.png" alt="Image" width="600" height="400" loading="lazy">
<em>The "Upload" button.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-79.png" alt="Image" width="600" height="400" loading="lazy">
<em>Matching columns to their corresponding languages. Image taken from the <a target="_blank" href="https://support.crowdin.com/translation-memory/#downloading-and-uploading-tm">Crowdin Documentation</a>.</em></p>
<p>To download translation memory:</p>
<ul>
<li>Click on the "Download" button. </li>
<li>Select the file format (either TMX, XLSX, or CSV).</li>
<li>Choose if you would like to download all languages or only a specific language pair.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tm-records-download-upload.png" alt="Image" width="600" height="400" loading="lazy">
<em>The "Download" button.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/download-tm.png" alt="Image" width="600" height="400" loading="lazy">
<em>Download TM.</em></p>
<p>The download should start after you click on the green "Download" button. </p>
<p>This is the CSV file that we get when we export the Translation Memory of our freeCodeCamp Course Project:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-19-at-5.19.49-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Exported CSV File.</em></p>
<h3 id="heading-how-to-assign-translation-memory-to-a-project">How to Assign Translation Memory to a Project</h3>
<p>To assign an existing TM to a project:</p>
<ol>
<li>Go to your project.</li>
<li>Go to the "Settings" tab.</li>
<li>Go to "Translation Memories".</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/assign-tm.png" alt="Image" width="600" height="400" loading="lazy">
<em>Settings tab.</em></p>
<ol start="4">
<li>Scroll down to find "Assigned Translation Memories".</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/assigned-tm.png" alt="Image" width="600" height="400" loading="lazy"></p>
<ol start="5">
<li>Select the Translation Memories that you would like to assign to your project. </li>
</ol>
<p><a target="_blank" href="https://support.crowdin.com/translation-memory/#prioritizing-tm">Crowdin mentions</a> that:</p>
<blockquote>
<p>When you assign a few TMs to the project, you can set the needed priority for each of them. As a result, TM suggestions from the TM with the higher priority will be displayed in the first place.</p>
</blockquote>
<p>💡 <strong>Tip:</strong> A higher number represents a higher priority. If a TM has a priority of 5, that would be higher than a priority of 1.</p>
<p>You can also change the default TM by clicking on the corresponding star icon.</p>
<p><strong>Important:</strong> Please note that Crowdin recently eliminated the need to use custom workflows to automatically apply Translation Memory matches. Now you can enable Translation Memory on the project settings, like you can see below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/image-13.png" alt="Image" width="600" height="400" loading="lazy">
<em>How to Enable Translation Memory Pre-Translation for New Content in the Project Settings. Screenshot provided by the Crowdin team.</em></p>
<h2 id="heading-glossary-1">Glossary</h2>
<p>Awesome! Now you know the most important aspects of TM on Crowdin, so let's check out the glossaries.</p>
<p>💡 <strong>Tip:</strong> Remember that a glossary allows you to store and manage your project's terminology to help your translators with more context and definitions.</p>
<h3 id="heading-how-to-create-a-glossary">How to Create a Glossary</h3>
<p>When you create a project, a glossary is automatically created but you can also create new ones that are independent from any project.</p>
<p>To create a glossary:</p>
<ul>
<li>Go to your profile.</li>
<li>Go to "Resources".</li>
<li>Click on "Glossaries".</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/glossaries-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>Glossaries</em></p>
<p>You will see a glossary for each project that you have created on Crowdin. </p>
<ul>
<li>Click on the green "Create Glossary" button.</li>
<li>Choose a name and a language for your glossary. </li>
<li>If you need to, assign it to a project.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/create-a-glossary.png" alt="Image" width="600" height="400" loading="lazy">
<em>Assign to a Glossary.</em></p>
<p>After this, you will see your new glossary in the list of glossaries. I created a new glossary called "Demo Glossary".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/demo-glossary.png" alt="Image" width="600" height="400" loading="lazy">
<em>List of Glossaries.</em></p>
<h3 id="heading-how-to-manage-glossary-terms">How to Manage Glossary Terms</h3>
<p>You can add, edit, and delete concepts and terms from your glossaries. Let's see how you can do this step by step.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/empty-glossary.png" alt="Image" width="600" height="400" loading="lazy">
<em>New Empty Glossary.</em></p>
<p><strong>💡 Tip:</strong> On Crowdin, concepts is not the same as a term. A concept is broader than a term. This is what <a target="_blank" href="https://support.crowdin.com/glossary/#managing-glossary-concepts-and-terms">the documentation</a> says about their difference:</p>
<blockquote>
<p>A concept incorporates glossary terms and their variations with multiple translations and other relevant information.</p>
</blockquote>
<p>To add a concept, click on the green "Add concept" button:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/add-concept-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Add concept.</em></p>
<p>You will need to write information about the new concept:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-19-at-6.08.32-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Add concept dialog.</em></p>
<p>The <a target="_blank" href="https://support.crowdin.com/glossary/#managing-glossary-concepts-and-terms">Crowdin documentation</a> describes the following concept details:</p>
<blockquote>
<p><strong>Definition:</strong> concept definition.<br><strong>Subject:</strong> a branch of knowledge the concept is related to.<br><strong>Note:</strong> short notes about a concept that might be helpful to translators.<br><strong>URL:</strong> URL to the web page with relevant information about a concept.<br><strong>Figure:</strong> URL to the relevant image.</p>
</blockquote>
<p>It also mentions the following <strong>term</strong> details:</p>
<blockquote>
<p><strong>Part of speech:</strong> e.g., noun, verb, adjective, etc.<br><strong>Type:</strong> e.g., full form, acronym, abbreviation, etc.<br><strong>Status:</strong> preferred, admitted, not recommended, obsolete.<br><strong>Gender:</strong> term gender.<br><strong>Description:</strong> term description.<br><strong>Note:</strong> short notes about a term that might be helpful to translators.<br><strong>URL:</strong> URL to the web page with relevant information about a term.</p>
</blockquote>
<p>After you create the term, you will see it in the list of terms for the glossary:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/glossary-term-demo.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>To edit or delete a glossary term, click on the three dots to the right to see additional options and choose an option. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/glosssary-term-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Glossary Term.</em></p>
<p>You can download or upload a glossary in the following formats: </p>
<ul>
<li>TBX (v2)</li>
<li>TBX (v3)</li>
<li>CSV</li>
<li>XLSX</li>
</ul>
<p>Just click on the corresponding button and you will be able to choose a file to upload or the format of the file to download.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/download-upload.png" alt="Image" width="600" height="400" loading="lazy">
<em>Upload and Download a Glossary.</em></p>
<p><a target="_blank" href="https://support.crowdin.com/glossary/#downloading-and-uploading-glossary">Crowdin suggests</a> that:</p>
<blockquote>
<p>If you upload a glossary in CSV or XLS/XLSX file formats, select the language for each column and the column value (term, description, or part of speech) in the configuration dialog.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-80.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting the columns. Image taken from the <a target="_blank" href="https://support.crowdin.com/glossary/#downloading-and-uploading-glossary">Crowdin documentation</a>.</em></p>
<h3 id="heading-how-to-assign-a-glossary-to-a-project">How to Assign a Glossary to a Project</h3>
<p>It is very easy to assign a glossary to a project on Crowdin. </p>
<p>You just need to:</p>
<ul>
<li>Go to your project.</li>
<li>Go to the "Settings" tab.</li>
<li>Go to "Glossaries".</li>
<li>Select the glossary (or glossaries) that you would like to assign to your project.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/glossaries-demo.png" alt="Image" width="600" height="400" loading="lazy">
<em>Project Glossaries.</em></p>
<p><strong>💡 Tip:</strong> To change the default glossary of a project, just click on the star icon of the corresponding glossary. The dark gray star marks the current default glossary.</p>
<p>You can also share glossaries across all your projects by checking the option "Share Glossaries" in your profile:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/share-glossaries.png" alt="Image" width="600" height="400" loading="lazy">
<em>Share Glossaries.</em></p>
<h3 id="heading-how-to-translate-the-glossary">How to Translate the Glossary</h3>
<p>Translating your glossary can be very helpful to use terms consistently in your target languages.</p>
<p>To translate your glossary, Crowdin recommends using the free <a target="_blank" href="https://crowdin.com/store/apps/glossary-translate-app">Translate Glossary</a> app.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translate-glossary.png" alt="Image" width="600" height="400" loading="lazy">
<em>Translate Glossary app.</em></p>
<p>If you install the app, you will be able to translate your glossary directly on Crowdin and choose which projects should have access to this app.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/install-translate-glossary.png" alt="Image" width="600" height="400" loading="lazy">
<em>Install the app.</em></p>
<h2 id="heading-quality-assurance-qa-checks-in-crowdin">Quality Assurance (QA) Checks in Crowdin</h2>
<p>Quality assurance is essential for every type of project and this is especially true for localization projects. One small typo or spelling mistake can make all the difference to your users. </p>
<p>This is why Crowdin implemented efficient quality assurance features to help you deliver the high-quality translations that your users deserve.</p>
<p>According to <a target="_blank" href="https://support.crowdin.com/qa-checks/">Crowdin</a>:</p>
<blockquote>
<p>QA checks help to detect some common mistakes easily and quickly. It’s recommended to review and resolve all QA check issues before building your project and downloading translations.</p>
</blockquote>
<p>The issues detected by the QA Checks include:</p>
<ul>
<li>Typos.</li>
<li>Missing commas.</li>
<li>Extra spaces.</li>
<li>Other common mistakes.</li>
</ul>
<h3 id="heading-how-to-configure-quality-assurance-qa-checks">How to Configure Quality Assurance (QA) Checks</h3>
<p>To configure QA checks and choose what you would like to check for in the translated strings, you just need to:</p>
<ul>
<li>Go to your project.</li>
<li>Go to the "Settings" tab.</li>
<li>Make sure that "Enable QA Checks" is selected.</li>
<li>Select what you would like to check for.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/qa-checks-settings.png" alt="Image" width="600" height="400" loading="lazy">
<em>The QA Checks category.</em></p>
<p>You can check:</p>
<ul>
<li>If a translation is empty.</li>
<li>If the translation is longer than the predefined length limit (if it exists).</li>
<li>Tags mismatch.</li>
<li>Spaces mismatch.</li>
<li>Variables mismatch.</li>
<li>Punctuation mismatch.</li>
<li>Character case mismatch.</li>
<li>Special characters mismatch.</li>
<li>"Incorrect translation" issues.</li>
<li>Spelling issues.</li>
<li>ICU Syntax errors.</li>
<li>Consistency with the glossary terms.</li>
<li>Duplicate translation.</li>
<li>FTL syntax errors.</li>
<li>Android syntax errors.</li>
</ul>
<p><strong>💡 Tip:</strong> For each of these QA checks, you can choose if you would like to show a warning to the user when the string is being saved or if you would like to go one step further and show an error.</p>
<p>To save your changes, click on the green "Save" button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/qa-save-button.png" alt="Image" width="600" height="400" loading="lazy">
<em>Save QA Checks.</em></p>
<h3 id="heading-how-to-check-quality-assurance-status">How to Check Quality Assurance Status</h3>
<p>Proofreaders and project managers can see the issues found by the quality assurance checks. </p>
<p>To see the current status, you just need to:</p>
<ul>
<li>Go to your project.</li>
<li>Go to the "Dashboard" tab. </li>
<li>Find the "QA Checks" status. </li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/qa-checks-status-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>QA Checks with no issues.</em></p>
<p>You will see one of the following status:</p>
<ul>
<li><strong>Off</strong>: When the QA checks are not enabled.</li>
<li><strong>In Progress</strong>: When the QA checks are working.</li>
<li><strong>No Issues</strong>: When the QA checks did not find any issues.</li>
<li><strong>Issues Found</strong>: When the QA checks has found issues.</li>
</ul>
<p>If you try to save a string with QA check issue, you will see a warning or an error. You can save it anyway, but you should always try to fix these issues first. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/qa-warning.png" alt="Image" width="600" height="400" loading="lazy">
<em>A warning from adding extra spaces.</em></p>
<p>💡 <strong>Tip:</strong> Clicking the "Autofix" button on the warning will try to fix the issue automatically. You can also save it anyway or cancel.</p>
<p>This is a sample image from the Crowdin documentation showing what you should see if quality assurance issues are found in your project:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-81.png" alt="Image" width="600" height="400" loading="lazy">
<em>QA checks issues found. Image taken from the <a target="_blank" href="https://support.crowdin.com/qa-checks/">Crowdin documentation</a>.</em></p>
<p>Quality assurance is a very important step that you should definitely take very seriously during your localization process.</p>
<h2 id="heading-how-to-upload-existing-translations">How to Upload Existing Translations</h2>
<p>Great. If you have existing translations, you can also upload them to your project. </p>
<p>You have three options:</p>
<ul>
<li>Upload them via the Translations Tab. </li>
<li>Upload them via the Language Page.</li>
<li>Upload them via the Translation Editor.</li>
</ul>
<h3 id="heading-how-to-upload-via-the-translations-tab">How to Upload Via the Translations Tab</h3>
<p>To upload them via the Translations Tab:</p>
<ul>
<li>Go to your project.</li>
<li>Go to "Upload existing translations".</li>
<li>Drag and drop your existing translations or select the files from your file system. </li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translations-tab-upload.png" alt="Image" width="600" height="400" loading="lazy">
<em>Upload translations via the Translations Tab.</em></p>
<p>According to Crowdin, the <a target="_blank" href="https://support.crowdin.com/uploading-translations/#key-value-formats">supported formats</a> for uploading translations include those that have a key-value structure, such as:</p>
<blockquote>
<p>Android XML, macOS/iOS Strings, Stringsdict, JSON, Chrome JSON, GO JSON, i18next JSON, FBT JSON, XLIFF, XLIFF 2.0, Java Properties, Play Properties, Java Properties XML, RESX, RESW, RES JSON, YAML, INI, Joomla INI, JS, FJS, PO, TS, QT TS, Blackberry, Symbian, Flex, BADA, TOML, Coffee, DKLANG, XAML, SRT, VTT, VTT2, SBV, SVG, DTD, CSV, RC, WXL, Maxthon, Haml, XLSX, PLIST, PHP, ARB, VDF.</p>
</blockquote>
<p>Crowdin also <a target="_blank" href="https://support.crowdin.com/uploading-translations/#text-and-html-based-formats">mentions</a> that:</p>
<blockquote>
<p>For files that do not have a defined structure, translation upload is handled by an experimental machine learning technology.  </p>
<p>This includes the following file formats: HTML, Front Matter HTML, Markdown, Front Matter Markdown, TXT, Generic XML, Web XML, DOCX, HAML, IDML, DITA, Wiki, FLSNP, MIF, and ADOC.</p>
</blockquote>
<h3 id="heading-how-to-upload-via-the-language-page">How to Upload Via the Language Page</h3>
<p>To upload them via the language page:</p>
<ul>
<li>Go to your project.</li>
<li>Go to "Dashboard".</li>
<li>Choose a target language.</li>
<li>Choose a file but instead of clicking on it, click on the three dots to its right to show more options. </li>
<li>Click on "Upload Translations".</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/upload-translations-language-page-2-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Upload translations from the language page.</em></p>
<p>When you click on this option, you will see some settings for the upload and for assigning the translations. Check the options that you need for your project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/upload-options.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-how-to-upload-via-the-translation-editor">How to Upload Via the Translation Editor</h3>
<p>Finally, you can also upload translations directly from the translation editor.</p>
<p>To do this:</p>
<ul>
<li>Click on the main menu. </li>
<li>In File, select "Upload Translations..."</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/upload-from-editor.png" alt="Image" width="600" height="400" loading="lazy">
<em>Upload Translations from the Translation Editor.</em></p>
<h3 id="heading-supported-file-formats-on-crowdin">Supported File Formats on Crowdin</h3>
<p>So far, we have mentioned different file formats that you can work with on Crowdin. But Crowdin supports more than 100+ file formats. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/100-file-formats.png" alt="Image" width="600" height="400" loading="lazy">
<em>Supports more than 100+ file formats.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/supported-file-formats.png" alt="Image" width="600" height="400" loading="lazy">
<em>Supported file formats in the Crowdin Store.</em></p>
<p>You can check the supported file formats in the following resources:</p>
<ul>
<li><a target="_blank" href="https://support.crowdin.com/supported-formats/">Supported Formats</a>.</li>
<li><a target="_blank" href="https://store.crowdin.com/categories/file-formats">File Formats in the Crowdin Store</a>.</li>
</ul>
<h2 id="heading-how-to-pre-translate-your-project">How to Pre-Translate your Project</h2>
<p>If your goal is to save time and improve your productivity, pre-translation through Machine Translation (MT) can be exactly what you need. </p>
<p>This is an automated process that applies computer-generated translations to your project when you upload a file. On Crowdin, you can configure machine translation engines to use this feature.</p>
<p>You have two alternatives to implement this process:</p>
<ul>
<li>Manual.</li>
<li>Automated.</li>
</ul>
<h3 id="heading-manual-pre-translation">Manual Pre-Translation</h3>
<p>To pre-translate your content manually via Machine Translation (MT):</p>
<ul>
<li>Go to your project.</li>
<li>Go to the "Dashboard" tab.</li>
<li>Click "Pre-translation".</li>
<li>Select via TM (Translation Memory) or via MT (Machine Translation).</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/pretranslation-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Pre-translation.</em></p>
<p>If you choose "via MT" (Machine Translation), you will have to choose your translation engine, target languages, and the files that you would like to pre-translate. You can also add labels.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-engine.png" alt="Image" width="600" height="400" loading="lazy">
<em>Pre-translate your project via MT.</em></p>
<h3 id="heading-automated-pre-translation">Automated Pre-Translation</h3>
<p>If you choose to automate the process, the system will pre-translate your new content automatically.</p>
<p>Recently, Crowdin added the possibility to enable Machine Translation Pre-Translation for new content in the project settings. If you enable this and you upload new content to your project, the system will translate automatically.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/image--1-.png" alt="Image" width="600" height="400" loading="lazy">
<em>Enable Machine Translation Pre-translate for new content. Screenshot provided by the Crowdin team.</em></p>
<h2 id="heading-offline-translation">Offline Translation</h2>
<p>Sometimes, you may need to work offline. Crowdin also has a great feature for this in situations where you or your team members would like to work on the translations offline.</p>
<p>To enable or disable this feature:</p>
<ul>
<li>Go to your project.</li>
<li>Go to the "Settings" tab.</li>
<li>Go to "Privacy and Collaboration".</li>
<li>Check (or uncheck) the "Allow offline translation" option.</li>
</ul>
<p><strong>💡Tip:</strong> This feature can be enabled or disabled by project managers.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/settings-tab-offline-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Allow offline translation.</em></p>
<p>Each file can be downloaded via the Editor or via the Language page.</p>
<h3 id="heading-how-to-download-a-file-via-the-editor">How to Download a File via the Editor</h3>
<p>To download a file via the Translation Editor:</p>
<ul>
<li>Click on the main menu at the top left.</li>
<li>Go to File</li>
<li>Click on "Download" or "Export in XLIFF".  </li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/download-files.png" alt="Image" width="600" height="400" loading="lazy">
<em>Download file via the editor.</em></p>
<h3 id="heading-how-to-download-a-file-via-the-language-page">How to Download a File Via the Language Page</h3>
<p>To download a file via the language page:</p>
<ul>
<li>Go to your project.</li>
<li>Go to "Dashboard".</li>
<li>Select a language.</li>
<li>In the list of files, click on the three dots next to the file that you would like to download to show more options.</li>
<li>Select "Download" or "Export in XLIFF".</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/language-download-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Download file via the language page.</em></p>
<h3 id="heading-how-to-download-all-files-for-a-target-language">How to Download All Files for a Target Language</h3>
<p>If you need to download all the files for a target language:</p>
<ul>
<li>Go to your project.</li>
<li>Go to "Dashboard".</li>
<li>Select a language.</li>
<li>Click on the up and down arrow icon (see the screenshot below). </li>
<li>Select "Download translations" or "Export in XLIFF".</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/download-files-from-language-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Download all translations.</em></p>
<h2 id="heading-exploring-public-projects">Exploring Public Projects</h2>
<p>Now that you know some of the most important features of Crowdin, you may also be asking yourself how you can explore other projects that are currently being translated on Crowdin. </p>
<p>If you click on "Projects" at the top and then you select "Explore Public Projects", you will see a page where you can explore public projects per topic and find popular projects on Crowdin.</p>
<p>You can also filter projects by searching on the search bar. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/explore-crowdin.png" alt="Image" width="600" height="400" loading="lazy">
<em>Explore Crowdin.</em></p>
<p>🎉 Congratulations. We just reached the end of the second part of the book, which was focused on Crowdin fundamentals. </p>
<p>Now we will dive into how teams and organizations can use Crowdin to manage their projects effectively. </p>
<h2 id="heading-crowdin-for-teams-and-organizations">🔹 <strong>Crowdin for Teams and Organizations</strong></h2>
<p>Awesome! Now let's see how Crowdin can help you if you are working with a team on a localization project or if you are the founder or manager of an organization that is interested in localizing a product or platform. </p>
<p>We will talk about how you can invite members, assign roles and tasks, and generate reports.</p>
<h3 id="heading-how-to-invite-project-members-and-contributors">How to Invite Project Members and Contributors</h3>
<p>To invite members to your project:</p>
<ul>
<li>Go to your project.</li>
<li>Go to the "Members" tab.</li>
<li>Click on the green "Invite" button.</li>
</ul>
<p>💡 <strong>Tip:</strong> You can also click on the gray "Invite People" button at the top left to reach the same options.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/members-tab-2-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Members tab.</em></p>
<p>You will need to enter information for these options before sending the invitation(s):</p>
<ul>
<li>Role.</li>
<li>Email or Crowdin username.</li>
<li>Message.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/invite-members.png" alt="Image" width="600" height="400" loading="lazy">
<em>Sending an invitation.</em></p>
<p>If you click on "Select role", you should see this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/select-role.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting a role.</em></p>
<p>By default, the "Translator" role will be selected.</p>
<p>You will also see three fields where you can choose which languages you would like to assign that role. For example, a contributor could be a translator for Japanese and a translator and proofreader for Spanish.</p>
<p><strong>💡 Tip:</strong> If you leave it blank, the role will apply to all languages but you can also choose specific languages. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/select-role-copy.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choosing specific languages.</em></p>
<p>We will talk more about member roles in just a moment. </p>
<p>💡 <strong>Tip:</strong> You can also change the role(s) of a member in the Profile section.</p>
<p>Once you are ready, click "Save" and you will go back to the main options. Click "Done" when you are ready to send the invitations.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/invite-members.png" alt="Image" width="600" height="400" loading="lazy">
<em>Sending an invitation.</em></p>
<h3 id="heading-how-to-send-invitation-links">How to Send Invitation Links</h3>
<p>If you would like to invite your team members through a link instead of sending them a direct invitation, you can do so too. </p>
<p>Just click on the "Get Link" button at the bottom to copy the link and send it to the person that you would like to invite to your project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/invite-members-link.png" alt="Image" width="600" height="400" loading="lazy">
<em>Get an invitation link.</em></p>
<p>You will see a confirmation message at the top.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/link-copied-to-clipboard.png" alt="Image" width="600" height="400" loading="lazy">
<em>Confirmation Message.</em></p>
<p>Then, you can paste the link wherever you need to, like an email.</p>
<h3 id="heading-how-to-manage-invitation-links">How to Manage Invitation Links</h3>
<p>To manage your invitation links, click on the "Manage Links" option:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/manage-links.png" alt="Image" width="600" height="400" loading="lazy">
<em>Manage Links.</em></p>
<p>You will see a list of all the invitation links you have generated, when you generated them, and the role(s) you granted to the invitee.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/invitation-links.png" alt="Image" width="600" height="400" loading="lazy">
<em>Invitation Links that have been generated.</em></p>
<p><strong>💡 Tip:</strong> You can copy them again by clicking on the link icon to their right or revoke them by clicking on "Revoke link".</p>
<p>If you click on "Done", you will go back to the previous screen and you can click the "X" button at the top to close it.</p>
<h2 id="heading-project-roles">Project Roles</h2>
<p>Now let's talk about the different roles that you can assign to your team members. Let's read the role descriptions provided by Crowdin in the <a target="_blank" href="https://support.crowdin.com/modifying-project-participants-roles/">documentation</a>:</p>
<h3 id="heading-owner">Owner</h3>
<blockquote>
<p>A person who created a project and has complete control over it. The owner can invite and manage project members, create projects, upload source and translation files to the project, set up integrations, etc.</p>
</blockquote>
<h3 id="heading-manager">Manager</h3>
<blockquote>
<p>Has similar rights as a project owner except the ability to manage some of the owner’s Resources (e.g., configuring MT engines, custom workflows, etc.) and delete projects.</p>
</blockquote>
<h3 id="heading-language-coordinator">Language Coordinator</h3>
<blockquote>
<p>Can manage certain features of a project only within languages they have access to.   </p>
<p>Language coordinators can translate and approve strings, manage project members and join requests, generate project reports, create tasks, and pre-translate the project content.   </p>
<p>Unlike managers, they do not have access to other project settings (e.g., project files, integrations, etc.).</p>
</blockquote>
<h3 id="heading-developer">Developer</h3>
<blockquote>
<p>Can upload files, edit translatable text, connect integrations, and use the API. Cannot manage project tasks, members and reports.</p>
</blockquote>
<h3 id="heading-proofreader">Proofreader</h3>
<blockquote>
<p>Can translate and approve strings. Doesn’t have access to project settings.</p>
</blockquote>
<h3 id="heading-translator">Translator</h3>
<blockquote>
<p>Can translate strings and vote for translations added by other members.</p>
</blockquote>
<h3 id="heading-blocked">Blocked</h3>
<blockquote>
<p>Doesn’t have access to the project.</p>
</blockquote>
<h3 id="heading-how-to-assign-or-change-roles">How to Assign or Change Roles</h3>
<p>You have two options to assign or change the role of a project member. </p>
<p>You can either:</p>
<ul>
<li>Set the role in the invitation.</li>
<li>Set the role on the member's profile page.</li>
</ul>
<h4 id="heading-how-to-set-the-role-in-the-invitation">How to Set the Role in the Invitation</h4>
<p>You can choose the role when you send an invitation to a new member.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/select-role.png" alt="Image" width="600" height="400" loading="lazy">
<em>Setting the role in the invitation.</em></p>
<h4 id="heading-how-to-setting-the-role-in-the-profile-page">How to Setting the Role in the Profile Page</h4>
<p>You can also go to the "Permissions" tab on the member's profile page to choose the roles that you would like to assign to that member and to choose the languages you would like to assign to them.</p>
<p>This is an example from the Crowdin <a target="_blank" href="https://support.crowdin.com/modifying-project-participants-roles/#languages-permissions">documentation</a>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-82.png" alt="Image" width="600" height="400" loading="lazy">
<em>Setting roles in the "Permissions" tab. Image taken from the Crowdin <a target="_blank" href="https://support.crowdin.com/modifying-project-participants-roles/#languages-permissions">documentation</a>.</em></p>
<p>Click on the "Save" button to save your changes.</p>
<h2 id="heading-project-managers">Project Managers</h2>
<p>Project managers play a key role for your team and for your project. They can have unlimited control over the entire project and they can help you coordinate and assign tasks to team members.</p>
<h3 id="heading-how-to-add-a-project-manager">How to Add a Project Manager</h3>
<p>Let's see how you can add a project manager to your project. You can assign the Manager role to a member when you send them an invitation:</p>
<ul>
<li>Go to your project.</li>
<li>Go to the "Members" tab. </li>
<li>Click on "Invite".</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/invite-button-4.png" alt="Image" width="600" height="400" loading="lazy">
<em>Members tab.</em></p>
<p>Click on "Translator". You will see all the possible roles. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/select-role-manager-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Select a role.</em></p>
<p>Choose "Manager". This will grant the member unlimited control over the entire project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/manager-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Manager role.</em></p>
<p>Alternatively, you can invite a Manager from your profile page:</p>
<ul>
<li>Go to your profile.</li>
<li>Go to the "Managers" tab.</li>
<li>Click on "Add Manager".</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/managers-tab-profile-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Add Manager.</em></p>
<p>Now you will need to enter the name or username of the manager, the message, the permissions that you would like to grant, and the projects that will be managed by this manager.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/invite-manager-from-profile.png" alt="Image" width="600" height="400" loading="lazy">
<em>Invite Manager.</em></p>
<h3 id="heading-editing-manager-permissions">Editing Manager Permissions</h3>
<p>You can also edit manager permissions on Crowdin. </p>
<p>To do this:</p>
<ol>
<li>Go to your profile.</li>
<li>Go to the "Managers" tab. You will see a list of the managers that you've added to your projects.</li>
<li>Double-click on the manager you would like to edit.</li>
</ol>
<p>This is an example from the <a target="_blank" href="https://support.crowdin.com/manager-permissions/#editing-manager-permissions">Crowdin documentation</a>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-83.png" alt="Image" width="600" height="400" loading="lazy">
<em>Managers tab example. Image taken from the <a target="_blank" href="https://support.crowdin.com/manager-permissions/#editing-manager-permissions">Crowdin documentation</a>.</em></p>
<ol start="4">
<li><p>Update the permissions for that manager.</p>
</li>
<li><p>Click on the "Save" button.</p>
</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/edit-permissions.png" alt="Image" width="600" height="400" loading="lazy">
<em>Imagen taken from the <a target="_blank" href="https://support.crowdin.com/manager-permissions/#editing-manager-permissions">Crowdin documentation</a>.</em></p>
<h3 id="heading-how-to-remove-a-manager">How to Remove a Manager</h3>
<p>To remove a manager:</p>
<ul>
<li>Go to your profile. </li>
<li>Go to the "Managers" tab.</li>
<li>Select the manager that you would like to remove.</li>
<li>Click "Remove".</li>
</ul>
<h3 id="heading-manager-vs-proofreader">Manager vs Proofreader</h3>
<p>On Crowdin, Managers and proofreaders have certain differences in their roles and permissions.</p>
<p>To explain this in more detail, the Crowdin team highlights this important question in the <a target="_blank" href="https://support.crowdin.com/modifying-project-participants-roles/#qa">documentation</a>:</p>
<blockquote>
<p>Q: <em>I’m a project owner. Do I need to invite a manager or a proofreader?</em>  </p>
<p>A: The main difference between a manager and a proofreader is the following: in addition to approving translations added by translators, managers can also invite and remove project members, upload source and translation files to the project, set up integrations, etc  </p>
<p>If you want to have a project member who should have access to the features mentioned above, you need to invite a project manager. Alternatively, if you plan to manage the project yourself, it will be enough to invite a proofreader.</p>
</blockquote>
<h2 id="heading-tasks">Tasks</h2>
<p>Organization is the key to the success of any project and Crowdin definitely knows this. This is why they incorporated very helpful tools called tasks on their platform to help you organize your project and coordinate tasks among your team members.</p>
<p>With tasks, you can assign specific files to your translators and proofreaders, set due dates, receive notifications, discuss tasks with other team members, and even split the words from the same file between different team members. </p>
<p>You can also track the status of each task in a visual board where you can drag and drop your tasks from one status to the next. </p>
<p>This sounds great, right? Let's see tasks in more detail.</p>
<h3 id="heading-how-to-create-a-new-task">How to Create a New Task</h3>
<p>To create a new task:</p>
<ul>
<li>Go to your project.</li>
<li>Click on the "Create Task" button.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tasks-tab-section-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Tasks on Crowdin.</em></p>
<p>💡 <strong>Tip:</strong> A task can only be assigned to one project.</p>
<p>After clicking on the button, you will see a form where you can enter all the details of your new task.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/new-task-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a new task.</em></p>
<p>The details that you can enter for a task include:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/task-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Task information (Part 1).</em></p>
<ul>
<li>Name.</li>
<li>Description.</li>
<li>Type (translate or proofread by own translators or by vendors).</li>
<li>Due date (optional).</li>
<li>Strings assigned to the task (all the strings of the selected file(s) or only strings modified during a specific time period).</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/task-3.png" alt="Image" width="600" height="400" loading="lazy">
<em>Task information (Part 2)</em></p>
<ul>
<li>Filter by labels (the labels that the strings of the task should have).</li>
<li>Exclude labels (the labels that the strings of the task should not have).</li>
<li>You can choose if you would like to skip strings that are already included in other tasks to avoid duplicate work by your team members.</li>
<li>Files that should be translated or proofread.</li>
<li>The target language(s). If the task has more than one target language, the system will create a task for each target language.</li>
<li>To assign team members to the task for each target language, click on the "Assign" option next to each language.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/assign-task-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Assign button.</em></p>
<p>When you click on "Assign", you will see the following options:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/assign-members-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Assign team members.</em></p>
<ul>
<li>Select the user(s) that you would like to assign to the task. You can search for users using the filter tool.</li>
<li>If you need to remove a user, just click on it on the list to the right. You can empty the list by clicking on the trash icon.</li>
</ul>
<p>💡 <strong>Tip:</strong> You can also choose if you would like to split the files to assign multiple users to the same file. </p>
<ul>
<li>Once you have all the users selected, click on the "Apply" button.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/select-all-users.png" alt="Image" width="600" height="400" loading="lazy">
<em>Users selected for the task.</em></p>
<p>You will see the profile image of the assigned team members in their corresponding language(s).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/assigned-members-list-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Assigned team member.</em></p>
<p>Click on "Create Task" to add the new task. Now you will see the task dashboard with a new task in each target language you selected. </p>
<p>In this case, I selected Spanish and assigned myself to the task:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/task-board-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Tasks dashboard.</em></p>
<h3 id="heading-the-tasks-board">The Tasks Board</h3>
<p>Now it's time to use the tasks board. This board is very helpful to see all the tasks of your project and track their status.</p>
<p>You will immediately notice that there are three possible statuses for a task: </p>
<ul>
<li>To Do</li>
<li>In Progress</li>
<li>Done</li>
</ul>
<p><strong>💡 Tip:</strong> Project managers can move a task from one status to another by dragging and dropping it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/task-board-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Tasks dashboard.</em></p>
<p>To see all the tasks in a specific target language, just click on that language and you will see them as "cards" with their corresponding information.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/task-board-2-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Tasks board.</em></p>
<p><strong>💡 Tip:</strong> If a task is assigned to you, you will see a gray star next to the name of the task. You can also search for tasks and filter them. </p>
<h3 id="heading-how-to-filter-tasks-by-members">How to Filter Tasks by Members</h3>
<p>You can see all the tasks assigned to a specific team member by using filters.</p>
<ul>
<li>Click on "Filters".</li>
<li>Click on "All users" (next to "Filter by").</li>
<li>Search for the username of the team member.</li>
<li>Click on the username.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/filter-by-members-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Filter tasks by members.</em></p>
<p>💡 <strong>Tip:</strong> To clear the filter, click on the "Clear filter" option to the right.</p>
<h3 id="heading-task-details">Task Details</h3>
<p>The task details is the basic information and structure of a task. With the details, you can see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-20-at-10.17.37-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>A Task.</em></p>
<ul>
<li>If the task is assigned to you (a gray star).</li>
<li>Task number.</li>
<li>Task name.</li>
<li>When the task was created.</li>
<li>If it will be translated and proofread by your own team or by vendors.</li>
<li>The profile pictures of the team members assigned to the task.</li>
<li>Word count.</li>
<li>Number of comments on the task.</li>
</ul>
<p>If you click on the task, you will see a more detailed overview:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/detailed-task-view.png" alt="Image" width="600" height="400" loading="lazy">
<em>Task details.</em></p>
<h3 id="heading-how-to-add-comments-to-a-task">How to Add Comments to a Task</h3>
<p>If you scroll down, you will also have the option to add comments to the task.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/detailed-task-view-2-copy-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Add comments to a task.</em></p>
<h3 id="heading-how-to-change-the-status-of-a-task">How to Change the Status of a Task</h3>
<p>From this detailed view, you will also be able to change the status of the task by just clicking on a button:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/change-status-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Task options.</em></p>
<p>If you change the status of a task using these buttons, you will also see the change reflected on the main task board, which would be equivalent to dragging and dropping it into a new status.</p>
<h3 id="heading-how-to-manage-tasks">How to Manage Tasks</h3>
<p>If you click on a task to check its details, and then you click on the three dots at the top right to display more options, you will be able to edit, close, and delete the task.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/edit-a-task-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>More options for managing tasks.</em></p>
<h3 id="heading-how-to-edit-a-task">How to Edit a Task</h3>
<p>This is what you will see if you try to edit a task:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/editing-a-task.png" alt="Image" width="600" height="400" loading="lazy">
<em>Edit task view.</em></p>
<p>It's very similar to what we saw when we created the task. You can change the strings assigned, the files, dates, and you can even reset the task scope and the progress for the assigned files.</p>
<h3 id="heading-how-to-close-a-task">How to Close a Task</h3>
<p>To close a task, you can click on "Close":</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/edit-a-task-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>More options for managing tasks.</em></p>
<h3 id="heading-how-to-see-all-closed-tasks">How to See All Closed Tasks</h3>
<p>To see all your closed tasks, you will need to:</p>
<ul>
<li>Go to your project.</li>
<li>Go to the "Tasks" tab.</li>
<li>Select "Closed" (next to "All").</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/closed-tasks.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>💡 <strong>Tip:</strong> "Done" and "Closed" are a bit different. A task can have the "Done" status but not closed. When a task is has the "Done" status, you will see a button on the card to close it, just like in the image below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/close-task-when-done-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Close button on a task marked as "Done".</em></p>
<h3 id="heading-how-to-reopen-a-task">How to Reopen a Task</h3>
<p>If you close a task and then realize that you need to reopen it, you just need to:</p>
<ul>
<li>Open the details of the closed task.</li>
<li>Click on the three dots to the right to see additional options.</li>
<li>Choose "Reopen".</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/reopen-task.png" alt="Image" width="600" height="400" loading="lazy">
<em>Reopen a task.</em></p>
<p>Now you will see the reopened task on the "To do" column of the tasks board.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/todo-task-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Reopened task.</em></p>
<h3 id="heading-how-to-delete-a-task">How to Delete a Task</h3>
<p>To delete a task:</p>
<ul>
<li>Open the task details.</li>
<li>Click on the three dots. </li>
<li>Select "Delete".</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/delete-a-task.png" alt="Image" width="600" height="400" loading="lazy">
<em>Delete a task.</em></p>
<h3 id="heading-how-to-see-all-tasks-assigned-to-you">How to See All Tasks Assigned to You</h3>
<p>If you are contributing to a project, you can see all the tasks assigned to you by following these steps:</p>
<ul>
<li>Go to your profile.</li>
<li>Go to the "To do" tab.</li>
<li>You will see all the tasks assigned to you and your archived tasks. </li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/see-all-my-tasks-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>The "To Do" tab on Profile.</em></p>
<p>💡 <strong>Tip:</strong> At the top, you will also find a search field to filter your tasks and an option to filter tasks by project.</p>
<p>This is the basic information that you will see for each task in this view:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/todo-tasks-profile.png" alt="Image" width="600" height="400" loading="lazy">
<em>Task in the "To Do" tab on the profile.</em></p>
<ul>
<li>Task number.</li>
<li>Task status.</li>
<li>Project.</li>
<li>Target language.</li>
<li>Word count.</li>
</ul>
<p>You will also see these two options to:</p>
<ul>
<li>Open the translation editor and start working on the task.</li>
<li>Archive the task.</li>
</ul>
<h3 id="heading-important-question-about-tasks">Important Question about Tasks</h3>
<p>Crowdin mentions this <a target="_blank" href="https://support.crowdin.com/enterprise/tasks/#qa">important question in the documentation</a>:</p>
<blockquote>
<p><strong>Q: <em>How the source file updates affect the existing translation and proofreading tasks?</em></strong>  </p>
<p>A: After the source file update, the list of source strings included in the task will be updated the following way:  </p>
<ul>
<li>The strings removed from the source file during the update will be removed from the task.  </li>
<li>The modified strings marked with the <em>Keep Translations</em> option will appear in the task with the new modified text.  </li>
<li>The newly added strings won’t affect the existing task in any way.  </li>
</ul>
<p>If the source file is restored to the revision, containing the removed strings, they will reappear in the task.</p>
</blockquote>
<h2 id="heading-project-reports">Project Reports</h2>
<p>As a project owner or project manager, reports can very helpful to understand your team's current progress and activity.</p>
<p>Crowdin has a reports feature where you can check your project status. This is a report of the demo project that we have been working with so far: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/project-reports.png" alt="Image" width="600" height="400" loading="lazy">
<em>Reports tab.</em></p>
<p>To access your project report:</p>
<ul>
<li>Go to your project.</li>
<li>Go to the "Reports" tab.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-20-at-11.31.20-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Report Part 1.</em></p>
<p>You will see the project status by default and you can switch to cost reports if you need to.</p>
<p>Here you can see some screenshots with the type of data that you can analyze and visualize with these reports:</p>
<ul>
<li>Total project size and the number of translatable strings.</li>
<li>Source language and target language.</li>
<li>Number of members.</li>
<li>Number of managers.</li>
<li>Number of translatable words.</li>
<li>Number of hidden words.</li>
<li>Number of duplicate words.</li>
<li>Number of translated words.</li>
<li>Number of approved words.</li>
<li>Number of new members.</li>
<li>Number of active members.</li>
</ul>
<p>You can see these reports with their corresponding increase or decrease percentage compared to the time period you selected.</p>
<p>You will also find charts of the translation activity with their corresponding legends.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-20-at-11.34.02-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Report (Part 2).</em></p>
<p>You will find charts of the "Proofreading Activity".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-20-at-11.34.11-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>And charts of the "Source Strings Activity", and so on.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-20-at-11.34.13-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can also change the report unit by clicking on this option:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/report-unit.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can choose: </p>
<ul>
<li>Strings.</li>
<li>Words.</li>
<li>Characters without spaces.</li>
<li>Characters with spaces.</li>
</ul>
<p>On the <a target="_blank" href="https://support.crowdin.com/project-reports/?q=reports">Crowdin documentation</a>, you can find examples of the Translation Activity chart, the Proofreading Activity chart, and the Source Strings Activity chart:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-activity-chart-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Translation Activity. Image taken from the <a target="_blank" href="https://support.crowdin.com/project-reports/?q=reports">Crowdin documentation</a>.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-20-at-11.41.30-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Proofreading Activity. Image taken from the <a target="_blank" href="https://support.crowdin.com/project-reports/?q=reports">Crowdin documentation</a>.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-20-at-11.41.46-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Source Strings Activity. Image taken from the <a target="_blank" href="https://support.crowdin.com/project-reports/?q=reports">Crowdin documentation</a>.</em></p>
<h3 id="heading-top-members-report">Top Members Report</h3>
<p>Your team members are fundamental for your localization process. Having a detailed report of your most dedicated and productive team members is always helpful. </p>
<p>To generate a report of your top members:</p>
<ul>
<li>Go to your project.</li>
<li>Go to the "Reports" tab.</li>
<li>Click on "Top Members".</li>
<li>Select a date range from the calendar.</li>
<li>Click on "Generate".</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/top-members-report.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You will see a list of your top members with:</p>
<ul>
<li>Their target languages</li>
<li>How many strings they translated</li>
<li>Target words</li>
<li>How many strings they approved</li>
<li>How many votes they submitted.</li>
</ul>
<p>You can also export your report in XLSX, CSV or JSON format and display or hide specific columns.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/export-report-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Export options.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/show-or-hide-columns.png" alt="Image" width="600" height="400" loading="lazy">
<em>Display or hide columns.</em></p>
<h2 id="heading-conversations-on-crowdin">Conversations on Crowdin</h2>
<p>Communication is essential for any successful project. You and your team members can communicate directly on Crowdin with the conversations feature.</p>
<p>With this feature, you can communicate with one or more team member in a private chat. Each conversation has a subject, so you can easily find them.</p>
<h3 id="heading-how-to-access-conversations">How to Access Conversations</h3>
<p>To access your conversations:</p>
<p>Click on the conversations icon at the top right, next to your profile picture.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/conversation-button-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Conversations button.</em></p>
<p>Go to "Create Conversation".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/create-conversations-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Create a Conversation.</em></p>
<p>You can search for users by their name or username and you can also filter users by project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/filter-users.png" alt="Image" width="600" height="400" loading="lazy">
<em>Filter users.</em></p>
<p>This is an example from the <a target="_blank" href="https://support.crowdin.com/conversations/">Crowdin Documentation</a>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-86.png" alt="Image" width="600" height="400" loading="lazy">
<em>Conversation. Image taken from the <a target="_blank" href="https://support.crowdin.com/conversations/">Crowdin documentation</a>.</em></p>
<h3 id="heading-how-to-manage-conversations-and-messages">How to Manage Conversations and Messages</h3>
<p>For conversations, you can:</p>
<ul>
<li>Change the subject for all the users in the conversation.</li>
<li>Mute the conversation to stop receiving notifications.</li>
<li>Add users.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-87.png" alt="Image" width="600" height="400" loading="lazy">
<em>Example conversation. Image taken from the <a target="_blank" href="https://support.crowdin.com/conversations/">Crowdin documentation</a>.</em></p>
<p>For individual messages within a conversation, you can:</p>
<ul>
<li>Share the message in the same conversation or in another conversation. </li>
<li>Mark the message as unread.</li>
<li>Edit your messages.</li>
<li>Delete your messages.</li>
<li>Report spam.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-88.png" alt="Image" width="600" height="400" loading="lazy">
<em>Example of managing messages. Image taken from the <a target="_blank" href="https://support.crowdin.com/conversations/#messages">Crowdin documentation</a>.</em></p>
<p>🎉 Awesome. Now you know the most important features of Crowdin for teams and organizations.</p>
<p>Let's dive into how you can integrate Crowdin with other services and how you can install apps to improve your productivity.</p>
<h2 id="heading-crowdin-integrations-and-productivity-tools">🔹 Crowdin Integrations and Productivity Tools</h2>
<p>One of the key characteristics of Crowdin is its connectivity. You can connect your project to different external services to import and export your files and translations as needed.</p>
<h2 id="heading-what-is-an-integration">What is an Integration?</h2>
<p>On Crowdin, an integration is a "connection" that you can make between your project and an external service to synchronize your files between these platforms automatically.</p>
<p>On the <a target="_blank" href="https://store.crowdin.com/">Crowdin store</a>, you can find over 600 apps and integrations that you can add to your project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Crowdin-store.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Crowdin Store.</em></p>
<p>You can filter them by:</p>
<ul>
<li>Collections.</li>
<li>Categories.</li>
<li>Partners.</li>
<li>QA Checks.</li>
</ul>
<p>To give you an idea of the types of apps and integrations that you can find, these are some of the featured apps and integrations:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/featured-integrations.png" alt="Image" width="600" height="400" loading="lazy">
<em>Featured apps and integrations.</em></p>
<p>Let's talk about a few of them in more detail. </p>
<h3 id="heading-github-integration">GitHub Integration</h3>
<p>If your project is hosted on a GitHub repository, the <a target="_blank" href="https://store.crowdin.com/github">GitHub integration</a> could be exactly what you need.</p>
<blockquote>
<p>Crowdin’s integration with GitHub synchronizes source and translation files between your GitHub repository and translation project in Crowdin. All translated and approved files will be automatically pushed as a pull request to the l10n branch in GitHub repository.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/GitHub-integration.png" alt="Image" width="600" height="400" loading="lazy">
<em>GitHub Integration.</em></p>
<p>To learn more about this integration, you can check out <a target="_blank" href="https://www.youtube.com/watch?v=8baL6VWnnZg">this tutorial</a> created by Crowdin.</p>
<h3 id="heading-github-crowdin-action">GitHub Crowdin Action</h3>
<p>If you need to upload and download files from your GitHub repository to your Crowdin project automatically, this action can be very helpful for you.</p>
<p>The <a target="_blank" href="https://store.crowdin.com/github-action">GitHub Crowdin Action</a> can:</p>
<ul>
<li>Upload source files to Crowdin.</li>
<li>Upload translations to Crowdin.</li>
<li>Downloads translations from Crowdin.</li>
<li>Create a PR with the translations.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/github-crowdin-action.png" alt="Image" width="600" height="400" loading="lazy">
<em>GitHub Crowdin Action.</em></p>
<p>To learn more about the GitHub Crowdin Action, check out <a target="_blank" href="https://www.youtube.com/watch?v=5b7BMuCoKGg">this tutorial</a> created by the Crowdin team.</p>
<h3 id="heading-google-drive-integration">Google Drive Integration</h3>
<p>Google Drive is very helpful to create, host, and share documents. With the Google Drive integration, you can translate your files very easily on Crowdin.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/google-drive-integration.png" alt="Image" width="600" height="400" loading="lazy">
<em>Google Drive Integration.</em></p>
<p>To learn more about this integration, you can check out <a target="_blank" href="https://www.youtube.com/watch?v=M_WbdDQmEP8">this tutorial</a> created by the Crowdin team.</p>
<h3 id="heading-ai-assistant">AI Assistant</h3>
<p>With the rise in popularity of Large Language Models (LLMs), artificial intelligence has become a very important tool for translation and localization. </p>
<p>Crowdin has a very helpful <a target="_blank" href="https://store.crowdin.com/localization-ai">AI Assistant</a> that you can install to help you and your team. It is described as:</p>
<blockquote>
<p>An AI chatbot for translators built on OpenAI’s ChatGPT API. The first version of this app works as a co-pilot for translators. (<a target="_blank" href="https://store.crowdin.com/localization-ai">Source: Crowdin</a>)</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/ai-assistant.png" alt="Image" width="600" height="400" loading="lazy">
<em>AI Assistant.</em></p>
<p>Crowdin mentions that the AI Assistant has these interesting features:</p>
<blockquote>
<p>Our AI Assistant has a prompt engineering feature, empowering translators to customize prompts before commencing a translation project. As a result, they can conveniently modify the context, enhancing precision and meaningful translations.</p>
</blockquote>
<p>To learn more about this integration, check out <a target="_blank" href="https://www.youtube.com/watch?v=DSEu0iQanc4">this tutorial</a> created by the Crowdin team.</p>
<h3 id="heading-visual-studio-code-integration">Visual Studio Code Integration</h3>
<p>If you are a developer who works with <a target="_blank" href="https://store.crowdin.com/visual-studio-code">Visual Studio Code</a>, then Crowdin also has you covered because the team developed an extension to help you to translate your project.</p>
<blockquote>
<p>Integrate your Visual Studio Code projects with Crowdin to optimize the localization process. <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=Crowdin.vscode-crowdin">IDE Plugin</a> allows uploading new source strings instantly to your Crowdin project and downloading translations. (<a target="_blank" href="https://store.crowdin.com/visual-studio-code">Source: Crowdin</a>)</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/visual-studio-code.png" alt="Image" width="600" height="400" loading="lazy">
<em>Visual Studio Code Integration.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/vs-code-extension.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Extensions Marketplace.</em></p>
<p>You can learn more about this extension on its <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=Crowdin.vscode-crowdin">official documentation</a> in the Visual Studio Code Extensions Marketplace.</p>
<h3 id="heading-video-captions-translator">Video Captions Translator</h3>
<p>If you or your organization need to translate video captions, Crowdin has an integration for that too. It is called <a target="_blank" href="https://store.crowdin.com/video-captions-translator">Video Captions Translator</a>.</p>
<blockquote>
<p>Professional translations for video subtitles. Setup integration once, define your localization workflow and spend less time managing translations.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/video-captions-translator.png" alt="Image" width="600" height="400" loading="lazy">
<em>Video Captions Translator.</em></p>
<p>To learn more about YouTube Captions Translation with Crowdin, you can check out <a target="_blank" href="https://store.crowdin.com/video-captions-translator">this tutorial</a> created by the Crowdin team.</p>
<h3 id="heading-google-sheets-integration">Google Sheets Integration</h3>
<p>If you use <a target="_blank" href="https://store.crowdin.com/spreadsheet-crowdin">Google Sheets</a> to manage your localization keys, you can add this integration to your project to map your columns to their corresponding fields on Crowdin, including:</p>
<ul>
<li>Key.</li>
<li>Source Text.</li>
<li>Target Languages (all project languages).</li>
<li>Labels.</li>
<li>Context.</li>
<li>Translation Maximum Length.</li>
</ul>
<p>Please note that the Crowdin team mentions that:</p>
<blockquote>
<p>It's worth noting that this integration will only sync the first sheet from your Google Sheet document.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/google-sheets.png" alt="Image" width="600" height="400" loading="lazy">
<em>Google Sheets Integration.</em></p>
<p>To learn more about the Google Sheets Integration, check out <a target="_blank" href="https://www.youtube.com/watch?v=7tOanqDiIJ8">this tutorial</a> created by the Crowdin team. </p>
<h3 id="heading-suggestions-diff-checker">Suggestions Diff Checker</h3>
<p>If you have ever asked for a tool that could help your translators and proofreaders compare translations very easily with visual cues, this app is for you. </p>
<p>Crowdin describes <a target="_blank" href="https://store.crowdin.com/diff-checker">Suggestions Diff Checker</a> as:</p>
<blockquote>
<p>A great helper for proofreaders and translators that compares two translations and shows the difference between them.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/suggestions-diff-checker.png" alt="Image" width="600" height="400" loading="lazy">
<em>Suggestions Diff Checker.</em></p>
<h3 id="heading-proofreading-diff">Proofreading Diff</h3>
<p>Proofreading is a very important task for the localization process. Proofreaders can edit the translations and make sure that they are as accurate as possible. </p>
<p>With the <a target="_blank" href="https://store.crowdin.com/proofreading-diff">Proofreading Diff</a> report app, you can:</p>
<blockquote>
<p>Track and analyze changes made during the proofreading process. This tool can help you provide a thorough feedback to translators about their work.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/proofreading-diff.png" alt="Image" width="600" height="400" loading="lazy">
<em>Proofreading Diff.</em></p>
<h3 id="heading-video-preview">Video Preview</h3>
<p>Translating the subtitles of a video without actually watching the video simultaneously can be quite challenging because having the full context of a string is very helpful to translate it accurately. </p>
<p>This is why Crowdin created a translator productivity app called <a target="_blank" href="https://store.crowdin.com/preview-video">Video Preview</a>. They describe it as:</p>
<blockquote>
<p>A handy tool that can be useful when you have video subtitles to translate. It allows you to specify the video URL for each file with subtitles, and enables translators to preview the video while working on the translation.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/video-preview.png" alt="Image" width="600" height="400" loading="lazy">
<em>Video Preview.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-96.png" alt="Image" width="600" height="400" loading="lazy">
<em>Video Preview in action. Image taken from the <a target="_blank" href="https://store.crowdin.com/preview-video">Crowdin Documentation</a>.</em></p>
<h3 id="heading-glossary-editor">Glossary Editor</h3>
<p>This is another helpful Crowdin application for managing your project glossaries.</p>
<p>Crowdin mentions that the <a target="_blank" href="https://store.crowdin.com/glossary-edit-app">Glossary Editor</a>:</p>
<blockquote>
<p>Allows you to add and change the terms from your glossaries directly in Crowdin Editor.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/glossary-editor.png" alt="Image" width="600" height="400" loading="lazy">
<em>Glossary Editor.</em></p>
<h3 id="heading-project-duplicator">Project Duplicator</h3>
<p>Have you ever wished that you could use a project as a template for another project and save yourself all the initial set up time?</p>
<p>If you have, then <a target="_blank" href="https://store.crowdin.com/create-project-app">Project Duplicator</a> is exactly what you need:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/project-duplicator.png" alt="Image" width="600" height="400" loading="lazy">
<em>Project Duplicator.</em></p>
<p>With Project Duplicator, you can copy the following settings from a project:</p>
<ul>
<li>Source language.</li>
<li>Quality assurance checks.</li>
<li>Source strings.</li>
<li>Translations.</li>
<li>Translation Memory.</li>
<li>Notifications.</li>
<li>Language Mapping.</li>
</ul>
<h3 id="heading-unity-integration">Unity Integration</h3>
<p>If you are a game developer and you work with Unity, this integration is exactly what you need.</p>
<p>With the <a target="_blank" href="https://store.crowdin.com/unity">Unity Integration</a>, you can:</p>
<blockquote>
<p>Translate the content within your tables (strings and assets) and download translations into Unity.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/unity.png" alt="Image" width="600" height="400" loading="lazy">
<em>Unity Integration.</em></p>
<p>This is an official screenshot of the Crowdin Plugin for Unity:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-101.png" alt="Image" width="600" height="400" loading="lazy">
<em>Imagen taken from the <a target="_blank" href="https://store.crowdin.com/unity">Crowdin Documentation</a>.</em></p>
<h3 id="heading-is-crowdin-slow-for-everyone-or-just-me">Is Crowdin slow for everyone or just me?</h3>
<p>Yes, this is the official name of a translator productivity tool in Crowdin! 🙂 It is a performance widget for measuring your internet connection. </p>
<p>Crowdin <a target="_blank" href="https://store.crowdin.com/internet-speed">mentions</a> that it can be helpful to:</p>
<blockquote>
<p>Know immediately if the slowness you experience is caused by your internet connection or it's a Crowdin performance issue.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/is-crowdin-slow.png" alt="Image" width="600" height="400" loading="lazy">
<em>Is Crowdin slow for everyone or just me?</em></p>
<p>This is an official screenshot of the widget:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-97.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image taken from the <a target="_blank" href="https://store.crowdin.com/internet-speed">Crowdin Documentation</a>.</em></p>
<h3 id="heading-units-converter">Units Converter</h3>
<p>You learned that localization is broader than translation. Units are a great example of this. </p>
<p>When you localize a product that includes units of length, area, mass, volume, temperature, speed, and more, you need to have a tool at hand to convert them quickly while you localize your content. </p>
<p>Crowdin mentions that:</p>
<blockquote>
<p>The app is especially convenient when localizing for cultures that use different measurement systems.</p>
</blockquote>
<p>This is where the <a target="_blank" href="https://store.crowdin.com/units_converter">Units Converter app</a> can save you a lot of time because you can have it on your Translation Editor and quickly convert units without pausing your localization process to go to another tool.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/units-converter.png" alt="Image" width="600" height="400" loading="lazy">
<em>Units Converter.</em></p>
<p>This is an official screenshot of the app:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-98.png" alt="Image" width="600" height="400" loading="lazy">
_Units Converter app. Image taken from the <a target="_blank" href="https://store.crowdin.com/units_converter">Crowdin Documentation</a>._</p>
<h3 id="heading-screenshots-uploader">Screenshots Uploader</h3>
<p>Visual context is essential for writing high-quality translations. </p>
<p>The <a target="_blank" href="https://store.crowdin.com/screenshots-uploader">Screenshots Uploader</a> app:</p>
<blockquote>
<p>Makes it easier for your team to receive visual context.</p>
</blockquote>
<p>You can:</p>
<ul>
<li>Allow translators to upload screenshots. </li>
<li>Paste screenshots from your clipboard history without saving them on your device.</li>
<li>Edit screenshots before uploading them with helpful tools like cropping, zooming in, and so on.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/screenshots-uploader.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshots Uploader.</em></p>
<h3 id="heading-directory-notifications">Directory Notifications</h3>
<p>The <a target="_blank" href="https://store.crowdin.com/directory-notification">Directory Notifications</a> app is helpful for project owners and managers because Crowdin will:</p>
<blockquote>
<p>Send an email notification whenever a directory of files in your Crowdin project gets translated or proofread.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/directory-notifications.png" alt="Image" width="600" height="400" loading="lazy">
<em>Directory Notifications.</em></p>
<p>This is an official screenshot of the app:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-100.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image taken from the <a target="_blank" href="https://store.crowdin.com/directory-notification">Crowdin Documentation</a>.</em></p>
<h3 id="heading-emoji-input-for-editor">Emoji Input for Editor</h3>
<p>Emojis are awesome, right? I think we can all agree on that. 😁 </p>
<p>Luckily for us, Crowdin has an <a target="_blank" href="https://store.crowdin.com/emoji">Emoji Input for the Translation Editor</a>. They describe it as:</p>
<blockquote>
<p>A Crowdin Editor emoji list app for easy access with an extensive search functionality.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/emoji-input.png" alt="Image" width="600" height="400" loading="lazy">
<em>Emoji Input for Editor.</em></p>
<p>This is an official screenshot of the app:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-99.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image taken from the <a target="_blank" href="https://store.crowdin.com/emoji">Crowdin Documentation</a>.</em></p>
<h3 id="heading-emoji-mismatch">Emoji Mismatch</h3>
<p>And now let's dive into helpful automated Quality Assurance (QA) checks for our project that are available for Enterprise Crowdin accounts.</p>
<p>The first one is <a target="_blank" href="https://store.crowdin.com/emoji-mismatch-custom">Emoji Mismatch</a>, which can help us to find:</p>
<blockquote>
<p>Missed, extra or mismatched emoji in the translation.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Emoji-Mismatch.png" alt="Image" width="600" height="400" loading="lazy">
<em>Emoji Mismatch.</em></p>
<p>Please note that this works with Crowdin Enterprise.</p>
<h3 id="heading-space-after-punctuation">Space After Punctuation</h3>
<p>This is a very helpful quality assurance tool that you can add to your project.</p>
<p>Crowdin mentions that <a target="_blank" href="https://store.crowdin.com/space-after-punctuation-custom">Space After Punctuation</a>:</p>
<blockquote>
<p>Checks whether the translation contains the spaces after the punctuation symbols.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/space-after-punctuation.png" alt="Image" width="600" height="400" loading="lazy">
<em>Space After Punctuation.</em></p>
<p>Please note that this works with Crowdin Enterprise. </p>
<h3 id="heading-url-localization">URL Localization</h3>
<p>This is a quality assurance tool that you can also install for your project. With <a target="_blank" href="https://store.crowdin.com/url-localization-custom">URL localization</a>, you can check:</p>
<blockquote>
<p>Mistakes in URLs in the translation according to QA check configuration.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/url-localization.png" alt="Image" width="600" height="400" loading="lazy">
<em>URL Localization.</em></p>
<p>Please note that this works with Crowdin Enterprise. </p>
<h3 id="heading-duplicated-words">Duplicated Words</h3>
<p>This is a great tool for the proofreading phase of the localization project. Crowdin mentions that <a target="_blank" href="https://store.crowdin.com/duplicated-words-custom">Duplicated Words</a>:</p>
<blockquote>
<p>Removes every second repeated word in translation.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/duplicated-words.png" alt="Image" width="600" height="400" loading="lazy">
<em>Duplicated words.</em></p>
<p>Please note that this works with Crowdin Enterprise. </p>
<h3 id="heading-time-format-consistency">Time Format Consistency</h3>
<p>Writing time in a consistent format is also very important when you are localizing a product.</p>
<p>Crowdin <a target="_blank" href="https://store.crowdin.com/time-format-consistency">mentions</a> that:</p>
<blockquote>
<p>This QA check verifies that time formats in the source and translated text match. It checks for time formats in the 24-hour format (HH:MM).</p>
<p>The QA check will give a positive result if the number and format of time instances are consistent between the source and translated text, and a negative result if there is a mismatch.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/time-format-consistency.png" alt="Image" width="600" height="400" loading="lazy">
<em>Time Format Consistency.</em></p>
<p>Please note that this works with Crowdin Enterprise. </p>
<h3 id="heading-camelcase-consistency-check">camelCase Consistency Check</h3>
<p>This quality assurance check helps you ensure that product names, brand names, or other names that should be written in camelCase follow the same format in the translation.</p>
<p>Crowdin <a target="_blank" href="https://store.crowdin.com/camelcase-check">mentions</a> that it:</p>
<blockquote>
<p>Validates that all camelCase words present in the source text are accurately retained in the translated text.</p>
<p>If a camelCase word in the source text is not found in the translated text, the check will fail and notify the translator with a detailed message.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/camelcase-consistency-check.png" alt="Image" width="600" height="400" loading="lazy">
<em>camelCase Consistency Check.</em></p>
<h3 id="heading-more-apps-and-integrations">More Apps and Integrations</h3>
<p>We have seen many helpful apps and integrations for your localization process. They can optimize your team's productivity and help you to provide high-quality translations.</p>
<p>But this is just the start. Crowdin has more than 600 apps and integrations for your project. You can find a full list on the <a target="_blank" href="https://store.crowdin.com/categories/all">Crowdin Store</a>. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/crowdin-store-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Crowdin Store.</em></p>
<p>If you click on them, you will find more details about what they do, how they do it, and you may even find the source code that implements the functionality.</p>
<p>You can also sort them by relevance, name, or date. </p>
<p>The tools that you need to be more productive and deliver high-quality translations to your users are just one click away. </p>
<h2 id="heading-how-to-translate-a-website-on-crowdin">🔹 How to Translate a Website on Crowdin</h2>
<p>Great work! We've reached a very important part of the book, how to translate a website on Crowdin.</p>
<h3 id="heading-how-to-translate-a-website-on-crowdin-1">How to Translate a Website on Crowdin</h3>
<p>There are three main approaches for translating a website on Crowdin:</p>
<ul>
<li>Integrations.</li>
<li>JS Proxy Translator.</li>
<li>Crowdin In-context.</li>
</ul>
<p>Since there are many technologies, frameworks, and libraries for web development and the internationalization process is very technology-specific, it is recommended to analyze all the options available and find the one that works best for your particular use case.</p>
<h3 id="heading-integrations-1">Integrations</h3>
<p>The web development world is incredibly diverse. We can create and host websites on a variety of services and develop them using different tools.</p>
<p>To support this variety of tools and services, Crowdin has developed many integrations with external platforms to import your text and send your translations to the Content Management System (CMS) of your choice.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translate-website-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Translate a Website on Crowdin.</em></p>
<p>For example, you can translate a website from WordPress, Webflow, Joomla, and other similar tools. </p>
<p>According to <a target="_blank" href="https://crowdin.com/blog/2020/12/17/website-translation-with-crowdin">Crowdin</a>:</p>
<blockquote>
<p>With Crowdin, you are not confined to any specific website building and hosting services.</p>
<p>We do not only have 15 apps, including <a target="_blank" href="https://store.crowdin.com/wix-proxy-translator">Wix</a>, <a target="_blank" href="https://store.crowdin.com/ghost-org-proxy-translator">Ghost</a>, <a target="_blank" href="https://store.crowdin.com/squarespace-proxy-translator">Squarespace</a> and <a target="_blank" href="https://store.crowdin.com/webflow-proxy-translator">Webflow</a>, that provide you with the best way to translate a website, but a separate <a target="_blank" href="https://store.crowdin.com/js-proxy-translator">JS Proxy</a> technology that will help you with the localization of any other website.</p>
</blockquote>
<p>Essentially, these technologies:</p>
<ul>
<li>Scan your web pages.</li>
<li>Detect the content that can be translated (strings).</li>
<li>Extract them in a format that can be localized.</li>
<li>Synchronize the translations with your original project.</li>
</ul>
<p>You just need to add a JavaScript snippet to your code and you will be ready to start translating.</p>
<p>These are some of the apps that you can install to start translating your website on various external services:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/apps-for-translation.png" alt="Image" width="600" height="400" loading="lazy">
<em>A list of Crowdin apps that you can install to <a target="_blank" href="https://crowdin.com/blog/2020/12/17/website-translation-with-crowdin">translate your website</a>.</em></p>
<p>If host your repository on GitHub or you use GitHub pages, you can also use Crowdin's <a target="_blank" href="https://store.crowdin.com/github">GitHub Integration</a> and the <a target="_blank" href="https://store.crowdin.com/github-action">GitHub Crowdin Action</a> to synchronize your website files and translations automatically.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/github-integrations.png" alt="Image" width="600" height="400" loading="lazy">
<em>GitHub Integrations.</em></p>
<h3 id="heading-js-proxy-translator">JS Proxy Translator</h3>
<p>Integrations are very helpful, but Crowdin also has an option that can help you with the localization of any website, irrespective of the service where it is hosted. </p>
<p>This approach to website localization on Crowdin is called <a target="_blank" href="https://store.crowdin.com/js-proxy-translator">JS Proxy Translator</a>. </p>
<p>Crowdin mentions that with this proxy, you can:</p>
<ul>
<li>Synchronize your sources and translated content.</li>
<li>Localize your website with minimum effort.</li>
<li>Extract source text without any coding.</li>
<li>Translate meta titles and description to be SEO-friendly.</li>
<li>Schedule when to synchronize your translations.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/js-proxy.png" alt="Image" width="600" height="400" loading="lazy">
<em>JS Proxy Translator.</em></p>
<p>Here we have two official screenshots provided by the Crowdin team that shows the steps required to configure the JS Proxy Translator. </p>
<p>The first step is to import your website content. You just need to enter your site URL and specify if you would like to sync the source files manually or daily by importing them automatically once a day.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-104.png" alt="Image" width="600" height="400" loading="lazy">
<em>JS Proxy Translator (Part 1). Image taken from the <a target="_blank" href="https://store.crowdin.com/js-proxy-translator">Crowdin documentation</a>.</em></p>
<p>Then, after your source text is translated, you can publish the translations to your website.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-105.png" alt="Image" width="600" height="400" loading="lazy">
<em>JS Proxy Translator (Part 2). Image taken from the <a target="_blank" href="https://store.crowdin.com/js-proxy-translator">Crowdin documentation</a>.</em></p>
<p>The Crowdin team does <a target="_blank" href="https://store.crowdin.com/js-proxy-translator">mention</a> that:</p>
<blockquote>
<p>You need to publish all content on your website before synchronizing it to your project for translation.</p>
</blockquote>
<p>To learn more about how to translate a website with a JS Proxy on Crowdin, check out <a target="_blank" href="https://www.youtube.com/watch?v=q_0byyBDRGI">this tutorial</a> created by the Crowdin team.</p>
<h3 id="heading-in-context-for-web">In-Context for Web</h3>
<p>The third approach to website localization on Crowdin is to translate the text directly within the website or web application using Crowdin In-Context.</p>
<p>The Crowdin team <a target="_blank" href="https://store.crowdin.com/in-context">mentions</a> that:</p>
<blockquote>
<p>Crowdin In-Context tool allows to translate texts directly within the actual web application. In such a way, the best translation quality is maintained.  </p>
<p>In-Context localization is tied up with the actual project created in Crowdin, under which translatable files are stored.  </p>
<p>This tool makes all the texts in the web app editable. Moreover, the translation process is real-time visible. Even the dynamic part of the application and strings that contain placeholders can be translated this way.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/crowdin-in-context.png" alt="Image" width="600" height="400" loading="lazy">
<em>Crowdin In-Context.</em></p>
<p>You can see it in action <a target="_blank" href="https://demo.crowdin.com/">here</a>, in the official Crowdin demo:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/demo-website.png" alt="Image" width="600" height="400" loading="lazy">
<em>Crowdin In-Context Demo.</em></p>
<p>If you log in to your Crowdin account, you will see this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/demo-website-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Crowdin In-Context Demo.</em></p>
<p>You will be able to click on each string on the website to translate it and when you save the translations, they will be synchronized with your Crowdin project.</p>
<p><strong>💡 Tip:</strong> To learn more about Crowdin In-Context, check out <a target="_blank" href="https://www.youtube.com/watch?v=ktfw7UsW3qw">this tutorial</a> created by the Crowdin team.</p>
<p>These are three different approaches for translating a website on Crowdin. Choosing the right one can make all the difference for your localization team. </p>
<p>Now that you know more about the most important Crowdin features, let's dive into freeCodeCamp's translation effort as a real-world example of a worldwide localization project powered by contributions from an amazing community of volunteers.</p>
<h2 id="heading-freecodecamps-translation-effort">🔹 freeCodeCamp's Translation Effort</h2>
<p>🎉 Awesome. Congratulations on reaching this part of the book. This proves that you are very interested in learning these skills.</p>
<p>Now that you know how to translate your project on Crowdin, let's see how freeCodeCamp's amazing community is translating our content into many world languages.</p>
<p>We'll see this from a potential contributor's point of view, emphasizing how to translate our content on Crowdin.</p>
<h3 id="heading-freecodecamps-contributing-guidelines">freeCodeCamp's Contributing Guidelines</h3>
<p>If you are a contributor who is interested in joining the translation effort, where should you start? </p>
<p>You should start by reading our <a target="_blank" href="https://contribute.freecodecamp.org/#/how-to-translate-files">Contributing Guidelines</a>. These are a set of articles that you can always refer to if you have any questions on how to join or how to start translating and proofreading. </p>
<p>There, you will find:</p>
<ul>
<li>A written overview of Crowdin.</li>
<li>How to get started.</li>
<li>How to select a project and a file.</li>
<li>How to translate the projects that we have on Crowdin. </li>
<li>How to proofread translations.</li>
<li>Translation best practices, and more!</li>
</ul>
<p>In <a target="_blank" href="https://contribute.freecodecamp.org/#/how-to-translate-files">this article</a>, you will find information on how to prepare yourself for contributions. </p>
<p>We recommend:</p>
<ul>
<li>Reading <a target="_blank" href="https://www.freecodecamp.org/news/help-translate-freecodecamp-language/">this announcement</a> written by Quincy Larson, the founder of freeCodeCamp. </li>
<li>Joining the <a target="_blank" href="https://forum.freecodecamp.org/c/contributors/3">community forum</a>. </li>
<li>Joining our <a target="_blank" href="https://discord.gg/PRyKn3Vbay">Discord chat server</a>.</li>
</ul>
<p>Our <a target="_blank" href="https://contribute.freecodecamp.org/#/how-to-translate-files">documentation</a> also mentions that working with a small team can be super helpful to stay motivated:</p>
<blockquote>
<p>Crowdin and other tools make it easy to contribute translations, but it's still a lot of work.  </p>
<p>We want you to enjoy contributing and not burn out or lose interest.  </p>
<p>A small group of 4-5 individuals is a good size to start your niche for your world language. You can then recruit even more friends to join the team.</p>
</blockquote>
<p>Currently, we have over 30 of the most widely spoken languages enabled on our Crowdin project. </p>
<p>Some of them are deployed on the live version of freeCodeCamp. You just need to select them from the dropdown menu to see a new language automatically.</p>
<p>If you do not see your languages listed, the documentation also mentions that:</p>
<blockquote>
<p>If you would like us to include a new world language, we recommend getting your friends excited about this.  </p>
<p>Once you have a small group of people (at least 4-5) interested and committed, we can hop on a call. We will explain all the details and walk you through some of the tools and processes.</p>
</blockquote>
<p>Once you have finished reading this part of the contributing guidelines, you can start to contribute. </p>
<p>First, let's take a look at the different roles that you can have as a freeCodeCamp contributor.</p>
<h3 id="heading-roles-for-the-freecodecamp-localization-process">Roles for the freeCodeCamp Localization Process</h3>
<p>You can contribute to freeCodeCamp's translation effort as a translator or proofreader.</p>
<p>Translators help us to translate curriculum files, documentation, and elements of freeCodeCamp's user interface like buttons and labels.</p>
<p>Proofreaders make sure that the translations are consistent, uniform in tone, and free from common issues such as typos.</p>
<h3 id="heading-language-leads">Language Leads</h3>
<p>Our language leads will be very happy to welcome you to our translation effort:</p>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/news/author/farhanhasin/">Farhan Hasin Chowdhury</a> (<a target="_blank" href="https://twitter.com/frhnhsin">@frhnhsin</a>) is leading the Bengali community.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/chinese/news/author/miyaliu/">Miya Liu</a> (<a target="_blank" href="https://twitter.com/miyaliu666">@miyaliu666</a>) is leading the Chinese community.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/italian/news/author/dario/">Dario Di Cillo</a> (<a target="_blank" href="https://twitter.com/_dariodc">@_DarioDC</a>) is leading the Italian community.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/japanese/news/author/yoko/">Yoko Matsuda</a> (<a target="_blank" href="https://twitter.com/_sidemt">@_sidemt</a>) is leading the Japanese community.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/korean/news/author/alison-yoon/">Alison Yoon</a> (<a target="_blank" href="https://twitter.com/aliyooncreative">@aliyooncreative</a>) is leading the Korean community.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/portuguese/news/author/daniel/">Daniel Rosa</a> (<a target="_blank" href="https://twitter.com/Daniel__Rosa">@Daniel__Rosa</a>) is leading the Portuguese community. </li>
<li><a target="_blank" href="https://www.freecodecamp.org/portuguese/news/author/nielda/">Nielda Karla Gonçalves de Melo</a> (<a target="_blank" href="https://twitter.com/NieldaKarla">@NieldaKarla</a>) is leading the Portuguese community.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/espanol/news/author/rafael/">Rafael Hernandez</a> (<a target="_blank" href="https://twitter.com/rafaeldavish">@RafaelDavisH</a>) is leading the Spanish community and the localization process.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/espanol/news/author/estefaniacn">Estefania Cassingena Navone</a> (<a target="_blank" href="https://twitter.com/EstefaniaCassN">@EstefaniaCassN</a>) is leading the Spanish YouTube channel.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/author/larymak/">Hillary Nyakundi</a> (<a target="_blank" href="https://twitter.com/larymak1">@larymak1</a>) is leading the Swahili community.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/ukrainian/news/author/anastasiia/">Anastasiia Buievych</a> (<a target="_blank" href="https://twitter.com/anisiangel?s=21&amp;t=3yJxu9lXXPDyxB6WYhRsWg">@anisiangel</a>) is leading the Ukrainian community.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/author/zaira/">Zaira Hira</a> (<a target="_blank" href="https://twitter.com/hira_zaira">@hira_zaira</a>) is leading the Urdu community.</li>
</ul>
<h3 id="heading-freecodecamp-on-crowdin">freeCodeCamp on Crowdin</h3>
<p>Just like I mentioned before, Crowdin is the translation platform we use. It is a localization management platform where individuals, teams, and organizations can localize their resources efficiently.</p>
<p>To access freeCodeCamp's projects on Crowdin:</p>
<p>Go to <a target="_blank" href="https://translate.freecodecamp.org/">translate.freecodecamp.org</a> and you will see the dashboard with the projects that we are currently focused on:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/freecodecamp.png" alt="Image" width="600" height="400" loading="lazy">
<em>freeCodeCamp.org on Crowdin.</em></p>
<p>We have three main projects:</p>
<ul>
<li><a target="_blank" href="https://translate.freecodecamp.org/curriculum">Coding Curriculum</a></li>
<li><a target="_blank" href="https://translate.freecodecamp.org/learn-ui">Learn User Interface</a></li>
<li><a target="_blank" href="https://translate.freecodecamp.org/contributing-docs">Contributing Documentation</a></li>
</ul>
<p>We also have other projects on Crowdin such as News UI, Other Courses, and Subtitles (Chinese).</p>
<h3 id="heading-how-to-choose-a-project-and-a-language">How to Choose a Project and a Language</h3>
<p>Once you're on our translation platform, you will need to choose a project. Let's say that you choose to translate the coding curriculum. </p>
<p>You just need to click on the project:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/freecodecamp-dashboard-crowdin.png" alt="Image" width="600" height="400" loading="lazy">
<em>Click on the project you would like to contribute work.</em></p>
<p>Once you click on the project, you will be taken to a list of available languages for translation.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/project-in-crowdin.png" alt="Image" width="600" height="400" loading="lazy">
<em>List of available languages for the Coding Curriculum project.</em></p>
<p>For each language, you will see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/language.png" alt="Image" width="600" height="400" loading="lazy"></p>
<ul>
<li>Its name.</li>
<li>Its language code.</li>
<li>A bar with two possible colors. Blue represents the translation progress and green represents the proofreading progress. </li>
<li>You can also see their corresponding percentages to the right.</li>
<li>The last number to the right represents the number of words to translate.</li>
</ul>
<p>You will also find an information panel on the right with:</p>
<ul>
<li>A brief description of the project.</li>
<li>The source language (English).</li>
<li>The number of contributors for that project.</li>
<li>How many source words exist in the project.</li>
<li>When the project was created and when it was last active.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/project-in-crowdin.png" alt="Image" width="600" height="400" loading="lazy">
<em>Check out the information on the right (the gray panel).</em></p>
<p>Now it's time to choose a language. </p>
<p>If you click on the language, you will be taken to the project structure with all the files and folder available for translation. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/spanish-modern-files-crowdin.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Coding Curriculum project structure for Spanish (Modern).</em></p>
<h4 id="heading-how-to-select-a-file">How to Select a File</h4>
<p>To enter the Translation Editor and start translating, just click on the name of a file that needs translation. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/selecting-a-file.png" alt="Image" width="600" height="400" loading="lazy">
<em>Select a file that needs translation. A file needs translation if the bar is not completely blue (translated) or green (proofread).</em></p>
<p>Please note that we usually prioritize translating the first three certifications.</p>
<p>💡 <strong>Tip:</strong> if you are not signed in to your Crowdin account or if you have not created your Crowdin account yet, you will be prompted to do so when you click on a file. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/creating-an-account.png" alt="Image" width="600" height="400" loading="lazy">
<em>This is the screen where you can log in to freeCodeCamp's translation platform. You can also sign up to create your Crowdin account.</em></p>
<p>If you're signing up for a new account, you will need to enter your email, choose your username, and your password. You will also receive an email from Crowdin asking you to click on a link to verify your email address. </p>
<h3 id="heading-the-translation-editor">The Translation Editor</h3>
<p>Congratulations. Now you have your Crowdin account and you are ready to start translating the file you selected. </p>
<p>Let's say that you clicked on the <code>**build-a-drum-machine.md**</code> file and you want to translate it into Spanish (Modern).</p>
<p>You will see a screen similar to this one:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/the-translator-ui.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Translation Editor. This is what you will see when you click on a file and sign in to your Crowdin account.</em></p>
<p>If you would like to learn more about how the editor works, click on "Next" to see more tips on the UI but if you would like to close this short tutorial, just click on the X at the top. </p>
<p>These are the seven steps of the short tutorial provided by Crowdin in case you would like to keep them as a reference:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tutorial-step-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Collaborate on translations in real-time.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tutorial-step-3.png" alt="Image" width="600" height="400" loading="lazy">
<em>Use context to make relevant translations.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tutorial-step-4.png" alt="Image" width="600" height="400" loading="lazy">
<em>Preview files.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tutorial-step-5.png" alt="Image" width="600" height="400" loading="lazy">
<em>Make translations from any device.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tutorial-step-6.png" alt="Image" width="600" height="400" loading="lazy">
<em>Switch to Side-by-side view to review translations faster.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tutorial-step-7.png" alt="Image" width="600" height="400" loading="lazy">
<em>That's all friends! This is the seventh and last step of the tutorial.</em></p>
<p>After you reach the final step, click "Close" and you will be in the Translation Editor. </p>
<p>This is where the magic happens. You can start translating, save your translations, use suggested translations and adapt them, and even upvote or downvote proposed translations. </p>
<p>To translate a string, just click on it or save your current translation to go to the next string.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translations-editor.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Translations Editor.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translations-editor-copy.png" alt="Image" width="600" height="400" loading="lazy">
<em>This is where you can write and save your translation.</em></p>
<p>💡 <strong>Tip:</strong> You can also write comments and mark them as issues to notify freeCodeCamp's staff and other contributors.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/comments-sample.png" alt="Image" width="600" height="400" loading="lazy">
<em>You can write comments for individual strings and mark them as issues.</em></p>
<h3 id="heading-how-to-translate-the-learn-interface">How to Translate the Learn Interface</h3>
<p>We also have specific guidelines for translating the Learn interface.</p>
<p>Our <a target="_blank" href="https://contribute.freecodecamp.org/#/how-to-translate-files?id=translate-the-learn-interface">documentation</a> mentions that:</p>
<blockquote>
<p>Our <code>/learn</code> interface relies on JSON files loaded into an i18n plugin to generate translated text. This translation effort is split across both Crowdin and GitHub.</p>
</blockquote>
<p>We translate the <code>intro.json</code> and <code>translations.json</code> files on Crowdin. If you are planning to translate strings from these files, please know that the Context information provided in Crowdin can be very helpful.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-68.png" alt="Image" width="600" height="400" loading="lazy">
<em>Example of the context information provided by Crowdin (<a target="_blank" href="https://contribute.freecodecamp.org/#/how-to-translate-files?id=on-crowdin">source</a>).</em></p>
<p>There are certain files that we cannot upload to Crowdin, such as <code>links.json</code>, <code>meta-tags.json</code>, <code>motivation.json</code>, and <code>trending.json</code>. These files are usually maintained by language leads but if you would like to help with these, please refer to <a target="_blank" href="https://contribute.freecodecamp.org/#/language-lead-handbook">this article</a>.</p>
<h3 id="heading-how-to-translate-the-documentation">How to Translate the Documentation</h3>
<p>Documentation is another essential resource for freeCodeCamp's mission because we can share important information, steps, and guidelines with potential contributors. </p>
<p>We do have certain guidelines for translating our documentation. You can <a target="_blank" href="https://contribute.freecodecamp.org/#/how-to-translate-files?id=translate-documentation">find them</a> in this article. It covers how to translate internal links in the translated documentation.</p>
<h3 id="heading-best-practices">Best Practices</h3>
<p>For any project, our goal should always be to follow the best practices, right? These are some of the <a target="_blank" href="https://contribute.freecodecamp.org/#/how-to-translate-files?id=translation-best-practices">best practices</a> that you should follow to translate freeCodeCamp's resources:</p>
<ul>
<li>Do not translate the content within <code>&lt;code&gt;</code> tags. These tags indicate text that is found in code and should be left in English.</li>
<li>Do not add additional content. If you feel a challenge requires changes in the text content or additional information, you should propose the changes through a GitHub issue or a pull request that modifies the English file.</li>
<li>Do not change the order of content.</li>
</ul>
<h3 id="heading-how-to-become-a-proofreader">How to Become a Proofreader</h3>
<p>If you join freeCodeCamp's localization effort, you can also <a target="_blank" href="https://contribute.freecodecamp.org/#/how-to-proofread-files?id=becoming-a-proofreader">become a proofreader</a>.</p>
<p>We will typically grant you proofreading access if you have been contributing to freeCodeCamp for a while.</p>
<p>If you would like to apply to become a proofreader, please reach out to us in our <a target="_blank" href="https://discord.gg/PRyKn3Vbay">contributors chat room</a>.</p>
<p>💡 <strong>Tip:</strong> Proofreaders can approve their own translations. However, we advise you to allow another proofreader to review your proposed translations to make sure that there are no errors or typos.</p>
<h3 id="heading-how-to-proofread-the-translations">How to Proofread the Translations</h3>
<p>When you become a proofreader, you will have special permissions in the Translations Editor. You will be able to see the current translations, edit them, and approve them.</p>
<p>You should consider the community scores determined by the upvotes and the downvotes when deciding which translations to approve.</p>
<p>When you approve a string, the automated process that we configured with the <a target="_blank" href="https://contribute.freecodecamp.org/#/how-to-proofread-files?id=proofread-translations">GitHub integration</a> on Crowdin will add it to our live platform:</p>
<blockquote>
<p>Approving a string in the proofreading view will mark it as complete and it will be downloaded in our next pull from Crowdin to GitHub.</p>
</blockquote>
<h3 id="heading-discord-chat-server-for-translators">Discord Chat Server for Translators</h3>
<p>If you have any questions or you would like to join our translation effort, you are welcome to join our <a target="_blank" href="https://contribute.freecodecamp.org/#/how-to-translate-files?id=prepare-yourself-for-contributions">Discord chat server</a> for translators.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/discord-chat-room.png" alt="Image" width="600" height="400" loading="lazy">
<em>Our Discord chat server.</em></p>
<p>Once you create your account and join the server, you will see a welcome message with the <code>**#start-here**</code> localization channel.</p>
<p>Excellent work. Now you are ready to start translating and join freeCodeCamp's localization effort.</p>
<h2 id="heading-summary">Summary</h2>
<p>Congratulations! We covered many topics related to localization and now you know more about how to localize your resources and platforms to reach users worldwide.</p>
<p>These are some key takeaways:</p>
<ul>
<li>In a globalized world where information is available with just a few clicks, localizing products, services, and platforms is essential if your goal is to reach users worldwide. Adapting them to different cultures will open doors for your team, your organization, and users around the world.</li>
<li>Crowdin is a powerful localization management platform focused on giving you and your team the tools you need to localize products and platforms that are constantly evolving. </li>
<li>freeCodeCamp's localization effort is a real-world example of a global community brought together by a common goal: providing free access to education around the world without language barriers. You can join too.</li>
</ul>
<p>I hope you liked this book on localization fundamentals. You are ready to start localizing your platform. Now is the right time to start. Localization can be exactly what you need to reach a global community of users.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ World Translation Month is Back – How to Help Translate freeCodeCamp into Your Native Language ]]>
                </title>
                <description>
                    <![CDATA[ One year has passed since freeCodeCamp held our first World Translation Month in September 2021.  Well, it’s September again – and here we are for the second installment of this month-long event. freeCodeCamp is holding our World Translation Month fo... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/world-translation-month-is-back-how-can-you-contribute-to-translate-freecodecamp-into-your-language/</link>
                <guid isPermaLink="false">66b0a7b97e889761ef17c3fd</guid>
                
                    <category>
                        <![CDATA[ freeCodeCamp.org ]]>
                    </category>
                
                    <category>
                        <![CDATA[ translation ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Daniel Rosa ]]>
                </dc:creator>
                <pubDate>Tue, 06 Sep 2022 14:00:47 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/09/World-Translation-Month-Article-Image-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>One year has passed since freeCodeCamp held our first World Translation Month in September 2021. </p>
<p>Well, it’s September again – and here we are for the second installment of this month-long event. freeCodeCamp is holding our World Translation Month for the second year in a row, taking place September 6th and running through the rest of the month.</p>
<h2 id="heading-what-is-world-translation-month">What is World Translation Month?</h2>
<p>World Translation Month is an initiative held by freeCodeCamp to help translate freeCodeCamp's curriculum into as many world languages as possible.</p>
<p>The event welcomes new localization contributors and thanks those who are already helping in the translation process. </p>
<p>During the inaugural event last year, freeCodeCamp held a Twitter Spaces session. During that session, we got to chat with contributors. We helped a lot of new people get started translating freeCodeCamp into their native language.</p>
<p>Rafael, the leader of the translation effort worldwide, published <a target="_blank" href="https://www.freecodecamp.org/news/world-translation-month-event/">this article</a> announcing the event. It provides some data on the efforts of translation up to that point.</p>
<p>You can also <a target="_blank" href="https://www.youtube.com/watch?v=jHbylSuuhIo">watch this short video</a> that contains messages from contributors all around the world about what World Translation Month means to them and how they're helping out.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/jHbylSuuhIo" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-translation-progress-to-date">Translation Progress to Date</h2>
<p>So much has happened in the twelve months since then. We've gotten contributors from many different languages. For example, Italian, Japanese, Portuguese, and Ukrainian now have the whole curriculum translated. </p>
<p>Others have started the process of translating the first three core certifications – Responsive Web Design (in its latest version), JavaScript, and Front-End Libraries – like Arabic, Bengali, French, German, Indonesian, Korean, Persian, Romanian, Russian, Turkish, and Urdu.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/languages2-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>freeCodeCamp's certifications translated to Italian and Japanese (above), Portuguese and Ukranian (below).</em></p>
<p>The community has also changed our focus a bit. This year, we made the decision to shift our attention to the freeCodeCamp publication. We've started translating our most popular tutorials into other world languages </p>
<p>We've now published these tutorials in many languages. Already, we have 475 articles in Spanish and over 1,000 articles in Chinese.</p>
<p>Portuguese has around 350 articles, and Italian has more than 200 articles translated. </p>
<p>The Japanese, Bengali, Arabic, and Urdu news sections have also been producing more and more translations for their publications.</p>
<p>This does not mean we are leaving the curriculum behind. In fact, both tasks are happening concurrently. Some contributors are focused on the curriculum, while others assist with the translation of the articles.</p>
<h2 id="heading-a-change-in-our-communication-channels">A Change in Our Communication Channels</h2>
<p>We've also changed how we communicate with our localization contributors. In June, we moved our chat rooms that we use to communicate with our contributors to our community Discord server. </p>
<p>This made it easier to interact with contributors. It has also helped them interact more easily with each other as well as with other members of the community who are learning to code. </p>
<p>The chat rooms for translations are under Localization, as seen in the image below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/image-196.png" alt="Image" width="600" height="400" loading="lazy">
<em>Localization chat rooms on the fCC Discord server</em></p>
<p>If campers need help with the curriculum in general, they can still ask questions on the <a target="_blank" href="https://forum.freecodecamp.org/">freeCodeCamp Forum</a>. </p>
<p>We have also set up sections in the different languages on the Forum to help people who have doubts during their journey across the curriculum but find it hard to ask their questions in English.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/09/image-197.png" alt="Image" width="600" height="400" loading="lazy">
<em>Several localized sections of the fCC forum are now available</em></p>
<h2 id="heading-the-goal-of-world-translation-month">The Goal of World Translation Month</h2>
<p>The goal of the World Translation Month is twofold:</p>
<ul>
<li>to thank our contributors for all they've been doing to bring freeCodeCamp to as many world languages as possible, and </li>
<li>to invite more contributors to be part of our translation effort.</li>
</ul>
<p>Quincy published an <a target="_blank" href="https://www.freecodecamp.org/news/help-translate-freecodecamp-language/">article</a> in June where you can read about how to reach out to us to offer your translation assistance. </p>
<p>We would also like to show our appreciation to our contributors who have taken their time to produce more and more texts in their languages. These translated curricula and articles make it possible for people around the world to learn to code in their native language.</p>
<h2 id="heading-world-translation-month-badges">World Translation Month Badges</h2>
<p>This year, we will once again give out badges to the contributors who have helped us translate articles for the publication throughout the month. Even though articles may vary in size, we understand that each one requires a ton of effort. </p>
<p>Translating articles is quite different from translating the curriculum. Contributors can translate a few strings in the curriculum and stop contributing. But each contributor is responsible for an entire article once they decide to translate it. So contributors begin and end the translation of articles they choose, something they excel at. </p>
<p>During the World Translation Month event, we will give all participants who have contributed throughout the month a World Translation Month Badge. </p>
<p>Also, at the end of the event, we will present special badges to the Top Translators who have made the most contributions in the month of September. </p>
<p>You will be able to display these badges on your freeCodeCamp forum profile if you want to do so.</p>
<h2 id="heading-thank-you-to-all-the-translators-contributors-and-proofreaders">Thank You to All the Translators, Contributors, and Proofreaders!</h2>
<p>If you would like to help translate freeCodeCamp's curriculum into any world language, visit our contributors’ channel on Discord, and read <a target="_blank" href="https://www.freecodecamp.org/news/help-translate-freecodecamp-language/">Quincy’s article</a> on how to contribute and learn more. </p>
<p>If you are part of this initiative and have contributed by volunteering to bring freeCodeCamp's vast resources to your native language, thank you! We offer our heartfelt gratitude and wishes that the process has helped you learn and has been fun for you. Keep up the great work!</p>
<h2 id="heading-end-of-world-translation-month-2022-update">End of World Translation Month 2022 Update</h2>
<p>World Translation Month has come to an end. And we would like to thank all the contributors who helped us translate the freeCodeCamp publication and the curriculum into many different world languages. </p>
<p>In the table below, you will find a list of our most prolific translators during the month of September grouped by language. Those who contributed the most will also get the Top Translator badge as an acknowledgement of the many hours they dedicated to this effort.</p>
<h3 id="heading-arabic">Arabic</h3>
<h4 id="heading-publication">Publication</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Publication Profile</td><td>Twitter Handle</td><td>Top Contributor</td></tr>
</thead>
<tbody>
<tr>
<td>Mostafa Higazy</td><td><a target="_blank" href="https://www.freecodecamp.org/arabic/news/author/mostafa/">mostafa</a></td><td></td></tr>
</tbody>
</table>
</div><h4 id="heading-curriculum">Curriculum</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Crowdin Username</td><td>Twitter Handle</td><td>Top Contributor</td></tr>
</thead>
<tbody>
<tr>
<td>Mohamed Elmetwaly</td><td>@Sakaly</td><td></td><td>✔️</td></tr>
<tr>
<td>Shady Moustafa</td><td>@Tozlock</td><td></td><td>✔️</td></tr>
<tr>
<td>abdelhakim</td><td>@abdelhakim</td><td></td><td></td></tr>
<tr>
<td>Khalid Benjelloun</td><td>@kmbenjel</td><td></td><td></td></tr>
<tr>
<td>Karim Elnemr</td><td>@karim.elnemr</td><td></td><td></td></tr>
<tr>
<td>Merna Maged</td><td>@mernamageed</td><td></td></tr>
</tbody>
</table>
</div><h3 id="heading-chinese">Chinese</h3>
<h4 id="heading-publication-1">Publication</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Publication Profile</td><td>Twitter Handle</td><td>Top Contributor</td></tr>
</thead>
<tbody>
<tr>
<td>Chengjun.L</td><td><a target="_blank" href="https://chinese.freecodecamp.org/news/author/chengjun/">chengjun</a></td><td></td><td>✔️</td></tr>
<tr>
<td>熊治杰</td><td><a target="_blank" href="https://chinese.freecodecamp.org/news/author/xiong/">xiong</a></td><td></td><td>✔️</td></tr>
<tr>
<td>PapayaHUANG</td><td><a target="_blank" href="https://chinese.freecodecamp.org/news/author/papayahuang/">papayahuang</a></td><td></td><td>✔️</td></tr>
<tr>
<td>luojiyin</td><td><a target="_blank" href="https://chinese.freecodecamp.org/news/author/luojiyin/">luojiyin</a></td><td><a target="_blank" href="https://twitter.com/vizrtluo">@vizrtluo</a></td><td>✔️</td></tr>
<tr>
<td>Yaxing Li</td><td><a target="_blank" href="https://chinese.freecodecamp.org/news/author/yaxing/">yaxing</a></td><td></td><td></td></tr>
<tr>
<td>赵翘楚</td><td></td><td></td></tr>
</tbody>
</table>
</div><h4 id="heading-curriculum-1">Curriculum</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Crowdin Username</td><td>Twitter Handle</td><td>Top Contributor</td></tr>
</thead>
<tbody>
<tr>
<td>ZhichengChen</td><td>@ZhichengChen</td><td></td><td>✔</td></tr>
<tr>
<td>Alan Luo</td><td>@iLtc</td><td></td><td>✔</td></tr>
<tr>
<td>HigginsLee</td><td>@HigginesLee</td><td></td><td></td></tr>
<tr>
<td>Wenwei Zheng</td><td>@Johnson-Zheng</td><td></td><td></td></tr>
<tr>
<td>Rin</td><td>@Rin</td><td></td><td></td></tr>
<tr>
<td>Miracle</td><td>@Miracle</td><td></td><td></td></tr>
<tr>
<td>Shan Li</td><td>@shanlillian33</td><td></td></tr>
</tbody>
</table>
</div><h3 id="heading-french">French</h3>
<h4 id="heading-publication-2">Publication</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Publication Profile</td><td>Twitter Handle</td><td>Top Contributor</td></tr>
</thead>
<tbody>
<tr>
<td>Ihssan</td><td><a target="_blank" href="https://www.freecodecamp.org/french/news/author/ihssand/">ihssand</a></td><td></td><td>✔️</td></tr>
<tr>
<td>Evan Hermier</td><td><a target="_blank" href="https://www.freecodecamp.org/french/news/author/evan/">evan</a></td><td></td><td></td></tr>
<tr>
<td>Pierre de Lépinay</td><td><a target="_blank" href="https://www.freecodecamp.org/french/news/author/pierre/">pierre</a></td><td></td><td></td></tr>
<tr>
<td>Guillaume Fassot</td><td><a target="_blank" href="https://www.freecodecamp.org/french/news/author/guillaume/">guillaume</a></td><td></td><td></td></tr>
<tr>
<td>lardeux jerome</td><td><a target="_blank" href="https://www.freecodecamp.org/french/news/author/chuck2kill/">chuck2kill</a></td><td></td><td></td></tr>
<tr>
<td>Bernard Ngandu</td><td><a target="_blank" href="https://www.freecodecamp.org/french/news/author/bernard-ng/">bernard-ng</a></td><td></td><td>✔️</td></tr>
<tr>
<td>Arthur Landurant</td><td><a target="_blank" href="https://www.freecodecamp.org/french/news/author/arthur/">arthur</a></td><td></td><td></td></tr>
<tr>
<td>Raphaël Seguin</td><td><a target="_blank" href="https://www.freecodecamp.org/french/news/author/raphael/">raphael</a></td><td></td><td></td></tr>
<tr>
<td>Aline Leroy</td><td><a target="_blank" href="https://www.freecodecamp.org/french/news/author/aline/">aline</a></td><td></td><td></td></tr>
<tr>
<td>Jean-Baptiste</td><td><a target="_blank" href="https://www.freecodecamp.org/french/news/author/jean-baptiste-lelandais/">jean-baptiste-lelandais</a></td><td></td><td></td></tr>
<tr>
<td>Emmanuel KPOGLI</td><td><a target="_blank" href="https://www.freecodecamp.org/french/news/author/emmanuel/">emmanuel</a></td><td></td><td></td></tr>
<tr>
<td>Jennyfer Collin</td><td><a target="_blank" href="https://www.freecodecamp.org/french/news/author/jennyfer/">jennyfer</a></td><td></td><td></td></tr>
<tr>
<td>Mehdi</td><td><a target="_blank" href="https://www.freecodecamp.org/french/news/author/soon/">soon</a></td><td></td></tr>
</tbody>
</table>
</div><h3 id="heading-german">German</h3>
<h4 id="heading-publication-3">Publication</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Publication Profile</td><td>Twitter Handle</td><td>Top Contributor</td></tr>
</thead>
<tbody>
<tr>
<td>Stephan Düsterhöft</td><td><a target="_blank" href="https://www.freecodecamp.org/german/news/author/stephan/">stephan</a></td><td><a target="_blank" href="https://twitter.com/stephandue">@stephandue</a></td><td>✔️</td></tr>
<tr>
<td>Alexander Hentschel</td><td><a target="_blank" href="https://www.freecodecamp.org/german/news/author/alexander/">alexander</a></td><td></td><td>✔️</td></tr>
</tbody>
</table>
</div><h3 id="heading-haitian-creole">Haitian Creole</h3>
<h4 id="heading-publication-4">Publication</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Publication Profile</td><td>Twitter Handle</td><td>Top Contributor</td></tr>
</thead>
<tbody>
<tr>
<td>Certil Rémy</td><td><a target="_blank" href="https://www.freecodecamp.org/haitian/news/author/certilremy/">certilremy</a></td><td><a target="_blank" href="https://twitter.com/certilremy">@certilremy</a></td><td>✔️</td></tr>
<tr>
<td>Chris Wesley Pierre</td><td></td><td></td><td></td></tr>
<tr>
<td>Vanessa Jacques</td><td></td><td></td><td></td></tr>
<tr>
<td>Marie Magdala Saintil</td><td></td><td></td><td></td></tr>
<tr>
<td>Esnold Jure</td><td></td><td></td><td></td></tr>
<tr>
<td>Danio Aneus</td><td></td><td></td><td></td></tr>
<tr>
<td>Jean Came Poulard</td><td></td><td></td><td></td></tr>
<tr>
<td>Jean Gerard Bousiquot</td><td></td><td></td></tr>
</tbody>
</table>
</div><h3 id="heading-hindi">Hindi</h3>
<h4 id="heading-publication-5">Publication</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Publication Profile</td><td>Twitter Handle</td><td>Top Contributor</td></tr>
</thead>
<tbody>
<tr>
<td>Kailash Choudhary</td><td></td><td></td><td></td></tr>
<tr>
<td>Nivedita Rajput</td><td></td><td></td></tr>
</tbody>
</table>
</div><h3 id="heading-indonesian">Indonesian</h3>
<h4 id="heading-publication-6">Publication</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Publication Profile</td><td>Twitter Handle</td><td>Top Contributor</td></tr>
</thead>
<tbody>
<tr>
<td>Kennan P</td><td></td><td></td><td></td></tr>
<tr>
<td>Bagus Aji Santoso</td><td></td><td></td><td>✔️</td></tr>
<tr>
<td>Peter Jose</td><td></td><td></td><td></td></tr>
<tr>
<td>Suci R. Putri</td><td></td><td></td><td></td></tr>
<tr>
<td>Haris Wirabrata</td><td></td><td></td><td></td></tr>
<tr>
<td>Hendri Priyambowo</td><td></td><td></td><td></td></tr>
<tr>
<td>Egar Pramana</td><td></td><td></td><td></td></tr>
<tr>
<td>Christine</td><td></td><td></td><td></td></tr>
<tr>
<td>Muhammad Cholid Hidayatullah</td><td></td><td></td><td></td></tr>
<tr>
<td>Ihsan</td><td></td><td></td><td></td></tr>
<tr>
<td>Kevin Matthew</td><td></td><td></td><td></td></tr>
<tr>
<td>Rizki Kurniawati</td><td></td><td></td><td></td></tr>
<tr>
<td>Muhammad Aswinsz</td><td></td><td></td></tr>
</tbody>
</table>
</div><h3 id="heading-italian">Italian</h3>
<h4 id="heading-publication-7">Publication</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Publication Profile</td><td>Twitter Handle</td><td>Top Contributor</td></tr>
</thead>
<tbody>
<tr>
<td>Roberto Pauletto</td><td><a target="_blank" href="https://www.freecodecamp.org/italian/news/author/rob1458/">rob1458</a></td><td></td><td>✔️</td></tr>
<tr>
<td>Alessandro Cipriani</td><td><a target="_blank" href="https://www.freecodecamp.org/italian/news/author/alessandro/">alessandro</a></td><td></td><td></td></tr>
<tr>
<td>Guido Cusani</td><td><a target="_blank" href="https://www.freecodecamp.org/italian/news/author/gducsn/">gducsn</a></td><td></td><td></td></tr>
<tr>
<td>Tiziano Caruana</td><td><a target="_blank" href="https://www.freecodecamp.org/italian/news/author/tiziano_caruana/">tiziano_caruana</a></td><td></td><td></td></tr>
<tr>
<td>Tobia Trinci</td><td><a target="_blank" href="https://www.freecodecamp.org/italian/news/author/tobia/">tobia</a></td><td></td><td></td></tr>
<tr>
<td>Luca De Angelis</td><td><a target="_blank" href="https://www.freecodecamp.org/italian/news/author/luca/">luca</a></td><td></td></tr>
</tbody>
</table>
</div><h3 id="heading-japanese">Japanese</h3>
<h4 id="heading-publication-8">Publication</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Publication Profile</td><td>Twitter Handle</td><td>Top Contributor</td></tr>
</thead>
<tbody>
<tr>
<td>Hitomi Kawahara</td><td><a target="_blank" href="https://www.freecodecamp.org/japanese/news/author/hitomi/">hitomi</a></td><td><a target="_blank" href="https://twitter.com/aiminlabs">@aiminlabs</a></td><td>✔️</td></tr>
<tr>
<td>Akiko Takano</td><td><a target="_blank" href="https://www.freecodecamp.org/japanese/news/author/akiko/">akiko</a></td><td><a target="_blank" href="https://twitter.com/akiko_pusu">@akiko_pusu</a></td><td></td></tr>
<tr>
<td>Mell</td><td><a target="_blank" href="https://www.freecodecamp.org/japanese/news/author/mell/">mell</a></td><td><a target="_blank" href="https://twitter.com/__me11_">@_<em>me11</em></a></td><td></td></tr>
<tr>
<td>Manabu Matsumoto</td><td><a target="_blank" href="https://www.freecodecamp.org/japanese/news/author/manabu/">manabu</a></td><td></td><td></td></tr>
<tr>
<td>Yuusuke Okamoto</td><td></td><td></td></tr>
</tbody>
</table>
</div><h4 id="heading-curriculum-2">Curriculum</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Crowdin Username</td><td>Twitter Handle</td><td>Top Contributor</td></tr>
</thead>
<tbody>
<tr>
<td>Kazuo Sekiguchi</td><td>@tomigo7</td><td></td><td>✔</td></tr>
<tr>
<td>mmatsumoto1026</td><td>@mmatsumoto1026</td><td></td><td></td></tr>
<tr>
<td>Akiko Takano</td><td>@akiko_pusu</td><td></td><td></td></tr>
<tr>
<td>k0dai</td><td>@k0dai</td><td></td><td></td></tr>
<tr>
<td>yoshikoueda_18</td><td>@yoshikoueda_18</td><td></td><td></td></tr>
<tr>
<td>samymammy</td><td>@samymammy</td><td></td></tr>
</tbody>
</table>
</div><h3 id="heading-portuguese-brazilian">Portuguese, Brazilian</h3>
<h4 id="heading-publication-9">Publication</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Publication Profile</td><td>Twitter Handle</td><td>Top Contributor</td></tr>
</thead>
<tbody>
<tr>
<td>Paula Simionato</td><td><a target="_blank" href="https://www.freecodecamp.org/portuguese/news/author/paulaflavia/">paulaflavia</a></td><td><a target="_blank" href="https://twitter.com/paulaflaviaps">@paulaflaviaps</a></td><td>✔️</td></tr>
<tr>
<td>Gabriel Galdino</td><td><a target="_blank" href="https://www.freecodecamp.org/portuguese/news/author/gabrielgaldino/">gabrielgaldino</a></td><td></td><td></td></tr>
<tr>
<td>Pedro Alves</td><td><a target="_blank" href="https://www.freecodecamp.org/portuguese/news/author/pedropaulo/">pedropaulo</a></td><td><a target="_blank" href="https://twitter.com/pedrotriforce">@pedrotriforce</a></td><td></td></tr>
<tr>
<td>Enoá Mourão</td><td><a target="_blank" href="https://www.freecodecamp.org/portuguese/news/author/enoa/">enoa</a></td><td></td><td></td></tr>
<tr>
<td>Rafael Fontenelle</td><td><a target="_blank" href="https://www.freecodecamp.org/portuguese/news/author/rafael-fontenelle/">rafael-fontenelle</a></td><td><a target="_blank" href="https://twitter.com/rafaelffbr1">@rafaelffbr1</a></td><td></td></tr>
<tr>
<td>Gabriel Lima</td><td><a target="_blank" href="https://www.freecodecamp.org/portuguese/news/author/gabriel/">gabriel</a></td><td><a target="_blank" href="https://twitter.com/gabriellimma">@gabriellimma</a></td><td></td></tr>
<tr>
<td>Thiago Costa Barbosa</td><td><a target="_blank" href="https://www.freecodecamp.org/portuguese/news/author/thiagocostabarbosa/">thiagocostabarbosa</a></td><td><a target="_blank" href="https://twitter.com/_thiagocb">@_thiagocb</a></td><td></td></tr>
<tr>
<td>Cássio Leodegário</td><td><a target="_blank" href="https://www.freecodecamp.org/portuguese/news/author/cassio/">cassio</a></td><td><a target="_blank" href="https://twitter.com/c_leodegario">@c_leodegario</a></td></tr>
</tbody>
</table>
</div><h4 id="heading-curriculum-3">Curriculum</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Crowdin Username</td><td>Twitter Handle</td><td>Top Contributor</td></tr>
</thead>
<tbody>
<tr>
<td>Ana Beatriz</td><td>@anabeatriz</td><td></td><td>✔</td></tr>
<tr>
<td>Dairenkon Majime</td><td>@moxu</td><td></td><td></td></tr>
<tr>
<td>Daniele Vilela</td><td>@danielevilela</td><td></td><td></td></tr>
<tr>
<td>Rafael Fontenelle</td><td>@rafael-fontenelle</td><td></td></tr>
</tbody>
</table>
</div><h3 id="heading-spanish">Spanish</h3>
<h4 id="heading-publication-10">Publication</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Publication Profile</td><td>Twitter Handle</td><td>Top Contributor</td></tr>
</thead>
<tbody>
<tr>
<td>Jose Sierra</td><td><a target="_blank" href="https://www.freecodecamp.org/espanol/news/author/jorge_sierra/">jorge_sierra</a></td><td><a target="_blank" href="https://twitter.com/Jorge_Sierra_1">@Jorge_Sierra_1</a></td><td></td></tr>
<tr>
<td>Anna Aimeri</td><td><a target="_blank" href="https://www.freecodecamp.org/espanol/news/author/anna/">anna</a></td><td><a target="_blank" href="https://twitter.com/aimerianna">@aimerianna</a></td><td></td></tr>
<tr>
<td>Josue</td><td><a target="_blank" href="https://www.freecodecamp.org/espanol/news/author/drifting/">drifting</a></td><td><a target="_blank" href="https://twitter.com/DriftingL_">@DriftingL_</a></td><td>✔️</td></tr>
<tr>
<td>Cristina Padilla</td><td><a target="_blank" href="https://www.freecodecamp.org/espanol/news/author/cristinapadilla/">cristinapadilla</a></td><td><a target="_blank" href="https://twitter.com/crispitipina">@crispitipina</a></td><td></td></tr>
<tr>
<td>Ian Cowley</td><td><a target="_blank" href="https://www.freecodecamp.org/espanol/news/author/ian-cowley/">ian-cowley</a></td><td></td><td></td></tr>
<tr>
<td>Eric</td><td><a target="_blank" href="https://www.freecodecamp.org/espanol/news/author/usdek/">usdek</a></td><td><a target="_blank" href="https://twitter.com/usdekx">@usdekx</a></td><td></td></tr>
<tr>
<td>Jhonathan Izquierdo</td><td><a target="_blank" href="https://www.freecodecamp.org/espanol/news/author/jhonathan/">jhonathan</a></td><td></td><td></td></tr>
<tr>
<td>Jose Gonzales</td><td><a target="_blank" href="https://www.freecodecamp.org/espanol/news/author/jose-gonzalez-nunez/">jose-gonzalez-nunez</a></td><td></td><td></td></tr>
<tr>
<td>Alvaro Beltran</td><td><a target="_blank" href="https://www.freecodecamp.org/espanol/news/author/alvaro-beltran/">alvaro-beltran</a></td><td><a target="_blank" href="https://twitter.com/BeltranAlvaro08">@BeltranAlvaro08</a></td><td></td></tr>
<tr>
<td>Jorge Torres Torres</td><td><a target="_blank" href="https://www.freecodecamp.org/espanol/news/author/jorge-torres-torres/">jorge-torres-torres</a></td><td><a target="_blank" href="https://twitter.com/jorgettor">@jorgettor</a></td><td></td></tr>
<tr>
<td>Miguel Rendón</td><td><a target="_blank" href="https://www.freecodecamp.org/espanol/news/author/micky/">micky</a></td><td><a target="_blank" href="https://twitter.com/mickyrend">@mickyrend</a></td></tr>
</tbody>
</table>
</div><h3 id="heading-swahili">Swahili</h3>
<h4 id="heading-publication-11">Publication</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Publication Profile</td><td>Twitter Handle</td><td>Top Contributor</td></tr>
</thead>
<tbody>
<tr>
<td>Annoh Kargusta</td><td><a target="_blank" href="https://www.freecodecamp.org/swahili/news/author/annoh/">annoh</a></td><td><a target="_blank" href="https://twitter.com/annoh_karlgusta">@annoh_karlgusta</a></td><td>✔️</td></tr>
<tr>
<td>Harold Oliver</td><td><a target="_blank" href="https://www.freecodecamp.org/swahili/news/author/harold/">harold</a></td><td></td><td>✔️</td></tr>
<tr>
<td>Neema Adam</td><td><a target="_blank" href="https://www.freecodecamp.org/swahili/news/author/neicore/">neicore</a></td><td><a target="_blank" href="https://twitter.com/neicoree">@neicoree</a></td><td>✔️</td></tr>
</tbody>
</table>
</div><h3 id="heading-turkish">Turkish</h3>
<h4 id="heading-publication-12">Publication</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Publication Profile</td><td>Twitter Handle</td><td>Top Contributor</td></tr>
</thead>
<tbody>
<tr>
<td>Utku</td><td></td><td></td><td></td></tr>
<tr>
<td>İlknur Beyaz</td><td></td><td></td><td></td></tr>
<tr>
<td>Dogan</td><td></td><td></td><td></td></tr>
<tr>
<td>Zehra Aydın</td><td></td><td></td></tr>
</tbody>
</table>
</div><h3 id="heading-ukrainian">Ukrainian</h3>
<h4 id="heading-publication-13">Publication</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Publication Profile</td><td>Twitter Handle</td><td>Top Contributor</td></tr>
</thead>
<tbody>
<tr>
<td>Rustam</td><td><a target="_blank" href="https://www.freecodecamp.org/ukrainian/news/author/rustamdocstranslator/">rustamdocstranslator</a></td><td></td><td>✔️</td></tr>
</tbody>
</table>
</div><h3 id="heading-urdu">Urdu</h3>
<h4 id="heading-publication-14">Publication</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Publication Profile</td><td>Twitter Handle</td><td>Top Contributor</td></tr>
</thead>
<tbody>
<tr>
<td>Ashique Ali</td><td><a target="_blank" href="https://www.freecodecamp.org/urdu/news/author/ali/">ali</a></td><td><a target="_blank" href="https://twitter.com/ashiqaliaslam">@ashiqaliaslam</a></td><td>✔️</td></tr>
<tr>
<td>Khurram Shahzad</td><td><a target="_blank" href="https://www.freecodecamp.org/urdu/news/author/khurram/">khurram</a></td><td><a target="_blank" href="https://twitter.com/Khurram78730833">@Khurram78730833</a></td><td></td></tr>
<tr>
<td>Syeda Farah Rehman</td><td><a target="_blank" href="https://www.freecodecamp.org/urdu/news/author/syeda/">syeda</a></td><td><a target="_blank" href="https://twitter.com/FarahSaifRahman">@FarahSaifRahman</a></td><td></td></tr>
<tr>
<td>talha</td><td><a target="_blank" href="https://www.freecodecamp.org/urdu/news/author/its-talha/">its-talha</a></td><td><a target="_blank" href="https://twitter.com/talha_inside">@talha_inside</a></td><td></td></tr>
<tr>
<td>Naveed</td><td><a target="_blank" href="https://www.freecodecamp.org/urdu/news/author/naveed/">naveed</a></td><td><a target="_blank" href="https://twitter.com/Naveed_Tech_T">@Naveed_Tech_T</a></td><td></td></tr>
<tr>
<td>Abdul Majid</td><td><a target="_blank" href="https://www.freecodecamp.org/urdu/news/author/abdul/">abdul</a></td><td><a target="_blank" href="https://twitter.com/abdulmajid_DHB">@abdulmajid_DHB</a></td><td></td></tr>
<tr>
<td>Muhammad Aadam Iqbal</td><td><a target="_blank" href="https://www.freecodecamp.org/urdu/news/author/aadam/">aadam</a></td><td><a target="_blank" href="https://twitter.com/AadamIqbal11">@AadamIqbal11</a></td></tr>
</tbody>
</table>
</div><h4 id="heading-curriculum-4">Curriculum</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Crowdin Username</td><td>Twitter Handle</td><td>Top Contributor</td></tr>
</thead>
<tbody>
<tr>
<td>Khurram Shahzad</td><td>@ksl1816</td><td></td><td>✔</td></tr>
</tbody>
</table>
</div><h3 id="heading-vietnamese">Vietnamese</h3>
<h4 id="heading-publication-15">Publication</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>Publication Profile</td><td>Twitter Handle</td><td>Top Contributor</td></tr>
</thead>
<tbody>
<tr>
<td>Thong Nguyen</td><td></td><td></td><td></td></tr>
<tr>
<td>Bùi Thế Vinh</td><td></td><td></td></tr>
</tbody>
</table>
</div> ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The freeCodeCamp World Translation Summit 2022 – Join the Translation Effort ]]>
                </title>
                <description>
                    <![CDATA[ Translation is a powerful tool that can change lives. Everyone should have access to free learning resources in their native language.  To achieve this, freeCodeCamp has started translating our curriculum into dozens of world languages, with the help... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-freecodecamp-world-translation-summit-2022-join-the-translation-effort/</link>
                <guid isPermaLink="false">66b1f884f3574ee89ababbd5</guid>
                
                    <category>
                        <![CDATA[ community ]]>
                    </category>
                
                    <category>
                        <![CDATA[ freeCodeCamp.org ]]>
                    </category>
                
                    <category>
                        <![CDATA[ translation ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Estefania Cassingena Navone ]]>
                </dc:creator>
                <pubDate>Mon, 04 Apr 2022 14:23:26 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/04/World-Translation-Summit-Image.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Translation is a powerful tool that can change lives. Everyone should have access to free learning resources in their native language. </p>
<p>To achieve this, freeCodeCamp has started translating our curriculum into dozens of world languages, with the help of thousands of volunteers around the world.</p>
<p>To honor our translators and proofreaders, we will be hosting a World Translation Summit. We will share updates on our translation effort and answer your questions. If you would like to join our translation effort, we will also onboard new volunteers.</p>
<p>📌 It would be great if you could <a target="_blank" href="https://calendly.com/freecodecamp-org/world-translation-summit-details?month=2022-04">join us</a>. We will have two sessions: Friday, April 8 at 9pm EST and Saturday, April 9 at 9 am EST.</p>
<p>In this article, you will find an overview of the progress of our translation effort: </p>
<ul>
<li><a class="post-section-overview" href="#heading-welcome-to-freecodecamp">Welcome to freeCodeCamp</a></li>
<li><a class="post-section-overview" href="#heading-our-translation-effort">Our Translation Effort</a></li>
<li><a class="post-section-overview" href="#heading-community-leaders">Community Leaders</a></li>
<li><a class="post-section-overview" href="#heading-student-testimonials">Student Testimonials</a></li>
<li><a class="post-section-overview" href="#heading-world-translation-summit-2022">World Translation Summit 2022</a></li>
</ul>
<h2 id="heading-welcome-to-freecodecamp">🔹 Welcome to freeCodeCamp</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/image-122.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><a target="_blank" href="https://www.freecodecamp.org/">freeCodeCamp</a> is a donor-supported 501(c)(3) nonprofit organization whose mission is to help people learn to code for free. We create and share thousands of interactive coding lessons, articles, and videos for anyone who wants to learn. </p>
<p>With <a target="_blank" href="https://www.freecodecamp.org/learn/">our curriculum</a>, you can learn to code for free, earn certifications, and build projects to start or expand your portfolio.</p>
<p>Since freeCodeCamp started in 2014, the community has grown steadily, and there are campers all over the world learning from freeCodeCamp's resources. </p>
<p>In 2019, we asked ourselves this question: could we expand our mission and help people learn to code in their native language? </p>
<p>The answer was "yes!", so we decided to take our mission one step further by translating and creating learning resources in other world languages. </p>
<p>From that moment, this has been one of our main goals because we believe that everyone should have access to free coding education around the world without any language barriers.</p>
<h2 id="heading-our-translation-effort">🔸 Our Translation Effort</h2>
<p>Our amazing team of volunteers and the members of our staff have achieved some impressive milestones so far and continue to progress on our translation effort. Let's see this in more detail.</p>
<h3 id="heading-curriculum">Curriculum</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/languages-menu.gif" alt="Image" width="600" height="400" loading="lazy">
<em>How to select a language from the dropdown menu.</em></p>
<p>The community has translated our curriculum into Spanish, Chinese, Italian, Portuguese, Ukrainian, and Japanese. These languages are already live and you can select them in the home page. </p>
<p>There has also been significant progress in many major world languages, including:</p>
<ul>
<li>Afrikaans</li>
<li>Arabic</li>
<li>Bengali</li>
<li>Catalan</li>
<li>Czech</li>
<li>Danish</li>
<li>Dutch</li>
<li>Finnish</li>
<li>French</li>
<li>German</li>
<li>Greek</li>
<li>Hatian Creole (Kreyòl)</li>
<li>Hebrew</li>
<li>Hindi</li>
<li>Hungarian</li>
<li>Korean</li>
<li>Norwegian</li>
<li>Persian (Farsi)</li>
<li>Polish</li>
<li>Romanian</li>
<li>Russian</li>
<li>Serbian</li>
<li>Swahili</li>
<li>Swedish</li>
<li>Thai</li>
<li>Turkish</li>
<li>Urdu</li>
<li>and Vietnamese</li>
</ul>
<p><strong>💡 Tip:</strong> you can learn more about our translation effort in this article written by Quincy Larson <a target="_blank" href="https://www.freecodecamp.org/news/world-language-translation-effort/">Learn to Code in Spanish, Chinese, and 30 Other Languages – freeCodeCamp's Translation Effort</a> </p>
<h3 id="heading-publications">Publications</h3>
<p>We have localized publications in the following languages, and are actively working on others:</p>
<p><strong><a target="_blank" href="https://www.freecodecamp.org/portuguese/news">Portuguese</a></strong><br>Our Portuguese publication has more than 190 translated articles and we publish new ones every week.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/image-137.png" alt="Image" width="600" height="400" loading="lazy">
<em>Portuguese Publication</em></p>
<p><strong><a target="_blank" href="https://www.freecodecamp.org/italian/news">Italian</a></strong><br>Our Italian publication has more than 85 translated articles and it is growing consistently every week. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/image-138.png" alt="Image" width="600" height="400" loading="lazy">
<em>Italian Publication</em></p>
<p><strong><a target="_blank" href="https://www.freecodecamp.org/japanese/news">Japanese</a></strong><br>Our Japanese publication has more than 30 translated articles and we are constantly translating new articles into Japanese.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/image-139.png" alt="Image" width="600" height="400" loading="lazy">
<em>Japanese Publication</em></p>
<p><a target="_blank" href="https://chinese.freecodecamp.org/news"><strong>Chinese</strong></a><br>Our Chinese publication has more than 720 translated articles and we publish new ones every week.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/image-140.png" alt="Image" width="600" height="400" loading="lazy">
<em>Chinese Publication</em></p>
<p><a target="_blank" href="https://www.freecodecamp.org/espanol/news"><strong>Spanish</strong></a><br>Our Spanish publication has more than 370 translated articles and we publish new ones every week.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/image-141.png" alt="Image" width="600" height="400" loading="lazy">
<em>Spanish Publication</em></p>
<p><strong><a target="_blank" href="https://www.freecodecamp.org/arabic/news">Arabic</a></strong><br>Our Arabic publication has more than 75 translated articles and we are translating new ones every week. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/image-136.png" alt="Image" width="600" height="400" loading="lazy">
<em>Arabic Publication</em></p>
<p><a target="_blank" href="https://www.freecodecamp.org/bengali/news"><strong>Bengali</strong></a><br>Our Bengali publication has more than 30 articles published and we translate new ones every week. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Bengali Publication</em></p>
<p><strong><a target="_blank" href="https://www.freecodecamp.org/ukrainian/news">Ukrainian</a></strong><br>We also have a Ukrainian publication where we translate articles for the community.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/ukrainian-news.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><strong>Urdu</strong><br>We are also working actively to start an Urdu publication. We already have 29 articles translated into Urdu and this publication will be live very soon.</p>
<h3 id="heading-translation-projects-and-new-certifications">Translation Projects and New Certifications</h3>
<p>We are also translating new projects and certifications into many world languages.</p>
<p><strong><a target="_blank" href="https://github.com/freeCodeCamp/LearnToCodeRPG">Learn to Code RPG</a></strong><br>Last year, freeCodeCamp launched a visual game novel created by <a target="_blank" href="https://lynnzheng.netlify.app/">Lynn Zheng</a> in which you can "teach yourself to code, make friends in the tech industry, and pursue your dream to become a developer." </p>
<p>The game has more than 600 Computer Science quiz questions to help you practice coding.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/b_IDdQzPRR4" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>You can help us <a target="_blank" href="https://translate.freecodecamp.org/learntocoderpg">translate the game</a> into your native language in Crowdin:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/learntocoderpg.gif" alt="Image" width="600" height="400" loading="lazy">
<em>Learn to Code RPG in Crowdin.</em></p>
<p><strong><a target="_blank" href="https://www.freecodecamp.org/news/rust-in-replit/">Rust Course</a></strong><br>We also have a Rust course created by <a target="_blank" href="https://www.freecodecamp.org/news/author/shaun/">Shaun Hamilton</a> that you can follow step by step on YouTube or interactively on Replit. This course is being translated into many world languages.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/image-144.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can help us <a target="_blank" href="https://translate.freecodecamp.org/other-courses">translate this course</a> in Crowdin.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/image-143.png" alt="Image" width="600" height="400" loading="lazy">
<em>Rust course in Crowdin.</em></p>
<p><strong><a target="_blank" href="https://www.freecodecamp.org/learn/2022/responsive-web-design/">Responsive Web Design Certification (Beta)</a></strong><br>We recently released a Beta version of the new Responsive Web Design curriculum that's focused on learning by building projects interactively. This new certification is available for translation in Crowdin.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/image-145.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot of the "Learn CSS Transforms by Building a Penguin" lesson.</em></p>
<p><strong><a target="_blank" href="https://www.freecodecamp.org/learn/relational-database/">Relational Database Certification (Beta)</a></strong><br>This year we also launched this certification created by <a target="_blank" href="https://www.freecodecamp.org/news/author/tom-m/">Tom Mondloch</a> in which you can learn how to work with relational databases step by step. We are also planning to translate this certification into other world languages.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/image-146.png" alt="Image" width="600" height="400" loading="lazy">
<em>Relational Database Certification (Beta)</em></p>
<p>As you can see, we have new and exciting projects that you can help us translate. By translating, you can learn while being part of an initiative that is transforming lives around the world. </p>
<h3 id="heading-discussion-forums">Discussion Forums</h3>
<p>When you are learning how to code, being able to ask questions is priceless. This is why we currently have <a target="_blank" href="https://forum.freecodecamp.org/">discussion forums</a> in: Spanish, Italian, Portuguese, Ukrainian, Japanese, and Chinese. On these forums, you can post coding questions and get help and advice from members of the community. </p>
<p><strong>💡 Tip:</strong> you can also share your projects and ask for feedback. There will always be members of the community who will be glad to share with you their thoughts and advice.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-27-at-6.11.34-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>freeCodeCamp's forums in Spanish, Italian, Portuguese, Ukrainian, Japanese, and Chinese.</em></p>
<h3 id="heading-localized-twitter-accounts">Localized Twitter Accounts</h3>
<p>We have active Twitter accounts in the following languages:</p>
<ul>
<li><strong>Spanish</strong>: <a target="_blank" href="https://twitter.com/freecodecampES">@freecodecampES</a></li>
<li><strong>Italian</strong>: <a target="_blank" href="https://twitter.com/freeCodeCampIT">@freeCodeCampIT</a></li>
<li><strong>Chinese:</strong> <a target="_blank" href="https://twitter.com/freeCodeCampZH">@freeCodeCampZH</a></li>
<li><strong>Bengali:</strong> <a target="_blank" href="https://twitter.com/freeCodeCampBN">@freeCodeCampBN</a></li>
<li><strong>Portuguese</strong>: <a target="_blank" href="https://twitter.com/freecodecampPT">@freecodecampPT</a></li>
<li><strong>Japanese</strong>: <a target="_blank" href="https://twitter.com/freecodecampJA">@freecodecampJA</a></li>
<li><strong>Arabic</strong>: <a target="_blank" href="https://twitter.com/freeCodeCampAR">@freeCodeCampAR</a></li>
<li><strong>Ukraine:</strong> <a target="_blank" href="https://twitter.com/freeCodeCampUK">@freeCodeCampUK</a></li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-27-at-6.02.30-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Localized Twitter Accounts</em></p>
<h3 id="heading-youtube-channels">YouTube Channels</h3>
<p>We believe that everyone should have the opportunity to choose learning resources for their learning style. This is why we also create and publish full video courses on YouTube. </p>
<p>Currently, we have four localized YouTube channels in:</p>
<ul>
<li><a target="_blank" href="https://www.youtube.com/freecodecampespanol">Spanish</a></li>
<li><a target="_blank" href="https://www.youtube.com/channel/UCjJ2wNr0beoxQN5_q3CaR1w">Chinese</a></li>
<li><a target="_blank" href="https://www.youtube.com/channel/UClHVZQqHLfbcbwFDwPfdB-A">Hindi</a></li>
<li><a target="_blank" href="https://www.youtube.com/channel/UCYl5XjGuTM1gbXUuxH1e0jA">Bengali</a></li>
</ul>
<p>We started our <strong>Spanish</strong> YouTube channel in early 2021. Now it has more than 76,000 subscribers, more than 1.6 million views, and more than 214,000 hours of watch time. So far, we have published five courses on HTML, CSS, JavaScript, Python, and React and we are creating new courses for the community. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/image-147.png" alt="Image" width="600" height="400" loading="lazy">
<em>freeCodeCamp's Spanish YouTube Channel</em></p>
<p>Our <strong>Chinese</strong> YouTube channel has more than 2,960 subscribers and two courses on JavaScript and Git.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/image-149.png" alt="Image" width="600" height="400" loading="lazy">
<em>freeCodeCamp's Chinese YouTube Channel</em></p>
<p>Our <strong>Hindi</strong> YouTube channel has more than 22,900 subscribers and 22 videos and courses on Python, Flutter, HTML and CSS, Android Development, C#, and TensorFlow.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/image-148.png" alt="Image" width="600" height="400" loading="lazy">
<em>freeCodeCamp's Hindi YouTube Channel</em></p>
<p>Our <strong>Bengali</strong> YouTube channel has more than 460 subscribers and one course on Responsive Web Design. We are working actively to create new courses in Bengali.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-8.png" alt="Image" width="600" height="400" loading="lazy">
<em>freeCodeCamp's Bengali YouTube Channel</em></p>
<p>We are working actively to start a <strong>Portuguese</strong> YouTube channel. </p>
<p>We also have a <a target="_blank" href="https://space.bilibili.com/335505768?spm_id_from=333.1007.0.0">freeCodeCamp bilibili</a> account for the Chinese community where contributors can share video tutorials and organize live events. </p>
<h3 id="heading-discord">Discord</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/06/image-116.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We also have <a target="_blank" href="https://discord.com/invite/KVUmVXA">Discord</a> where you can can join the freeCodeCamp community, ask questions, learn how to contribute, and interact with other members of the community. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/06/image-115.png" alt="Image" width="600" height="400" loading="lazy">
<em>Some of our Discord chatrooms for the localization effort.</em></p>
<h2 id="heading-community-leaders">🔸 Community Leaders</h2>
<p>Now let me introduce you to the community leaders. They are native speakers of their respective languages and their tasks include onboarding volunteers, creating resources, translating articles, preparing events and making sure that everything works smoothly for volunteers.</p>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/arabic/news/author/islam/">Islam Mahfouz</a> (<a target="_blank" href="https://twitter.com/codezilla_">@codezilla_</a>) is leading the Arabic community. </li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/author/farhanhasin/">Farhan Hasin Chowdhury</a> (<a target="_blank" href="https://twitter.com/frhnhsin">@frhnhsin</a>) is leading the Bengali community. </li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/author/joy/">Joy Shaheb</a> (<a target="_blank" href="https://twitter.com/joyshaheb">@JoyShaheb</a>) is leading the Bengali YouTube channel. </li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/author/miyaliu/">Miya Liu</a> (<a target="_blank" href="https://twitter.com/miyaliu666">@miyaliu666</a>) is leading the Chinese community. </li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/author/ilenia/">Ilenia Magoni</a> (<a target="_blank" href="https://twitter.com/ieahleen">@ieahleen</a>) is leading the Italian community. </li>
<li><a target="_blank" href="https://www.freecodecamp.org/italian/news/author/dario/">Dario Di Cillo</a> (<a target="_blank" href="https://twitter.com/_DarioDC">@_DarioDC</a>) is leading the Italian community.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/author/yoko/">Yoko Matsuda</a> (<a target="_blank" href="https://twitter.com/_sidemt">@_sidemt</a>) is leading the Japanese community. </li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/author/daniel-rosa/">Daniel Rosa</a> (<a target="_blank" href="https://twitter.com/Daniel__Rosa">@Daniel__Rosa</a>) is leading the Portuguese community. </li>
<li><a target="_blank" href="https://www.freecodecamp.org/portuguese/news/author/nielda/">Nielda Karla Gonçalves de Melo</a> (<a target="_blank" href="https://twitter.com/NieldaKarla">@NieldaKarla</a>) is leading the Portuguese YouTube channel.</li>
<li><a target="_blank" href="https://twitter.com/rafaeldavish">Rafael Hernandez</a> (<a target="_blank" href="https://twitter.com/rafaeldavish">@RafaelDavisH</a>) is leading the Spanish community.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/author/estefaniacn">Estefania Cassingena Navone</a> (<a target="_blank" href="https://twitter.com/EstefaniaCassN">@EstefaniaCassN</a>) is leading the Spanish YouTube channel. </li>
<li><a target="_blank" href="https://www.freecodecamp.org/ukrainian/news/author/anastasiia/">Anastasiia Buievych</a> (<a target="_blank" href="https://twitter.com/anisiangel?s=21&amp;t=3yJxu9lXXPDyxB6WYhRsWg">@anisiangel</a>) is leading the Ukrainian community.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/author/zaira/">Zaira Hira</a> (<a target="_blank" href="https://twitter.com/hira_zaira">@hira_zaira</a>) is leading the Urdu community.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/author/larymak/">Hillary Nyakundi</a> (<a target="_blank" href="https://twitter.com/larymak1">@larymak1</a>) is leading the Swahili community.</li>
</ul>
<h2 id="heading-student-testimonials">🔹 Student Testimonials</h2>
<p>Our learners inspire us and motivate us every day. The best way to show the impact of our translation effort around the world is to read students' testimonials on how freeCodeCamp has changed their lives and impacted their careers. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/testimonials.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-spanish-testimonials">Spanish Testimonials:</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/spanish-1-blurred-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Spanish Testimonial</em></p>
<blockquote>
<p><strong>English Translation:</strong><br>"I brought a web development course. I decided to share what I learned. The excitement in their faces and their motivation to learn is amazing. They registered for the Responsive Web Design course at @freeCodeCampES."  </p>
<ul>
<li>Translation by Estefania Cassingena Navone.</li>
</ul>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/spanish-2-blurred.png" alt="Image" width="600" height="400" loading="lazy">
<em>Spanish Testimonial</em></p>
<blockquote>
<p><strong>English Translation:</strong><br>"I don't think there is anything better for someone who wants to start programming than @freeCodeCampES courses."  </p>
<ul>
<li>Translation by Estefania Cassingena Navone.</li>
</ul>
</blockquote>
<h3 id="heading-chinese-testimonials">Chinese Testimonials:</h3>
<p>Testimonial by <a target="_blank" href="https://chinese.freecodecamp.org/news/author/zhichengchen/">陈志成 ZhichengChen</a>:</p>
<blockquote>
<p>freeCodeCamp 最吸引我的地方不仅在于超棒的在线课程，更在于背后优秀的国际化开源团队。在这里我可以通过协作翻译、发表文章、分享视频、贡献项目等方式参与到开源世界里来，可以有机会和世界各地的贡献者交流，甚至会收到 Quincy 的连线问候。参与开源是技术快速提升的途径之一，开源也是一种精神，更是一种生活态度。freeCodeCamp 里面有很多手册类文章，和其它手册不同的是，freeCodeCamp 里面的手册更侧重于实践，是一种很棒的学习方式。我一般会把每一个操作步骤实践一遍，然后再通过翻译加深理解，等到工作中用到相应的知识再回过头来过一下手册，从熟悉到掌握再到慢慢精通，既参与了开源贡献，又提升了技术水平。</p>
<p><strong>English Translation:</strong><br>"What I like the most about freeCodeCamp is not only the great online courses, but also the great international open source team behind it. Here you can participate in the open source world by collaborating on translations, posting articles, sharing videos, contributing to projects, and more. You can have the opportunity to communicate with contributors from all over the world, and even receive a “hello” from Quincy. freeCodeCamp has a lot of manuals, but unlike other manuals, the freeCodeCamp manuals are more hands-on, which is a great way to learn. I usually practice each operation step once, and then deepen my understanding through translation. When I use the corresponding knowledge in my work and then go back to the manual, from familiarity to mastery to slowly become proficient, to participate in open source contributions, and to improve the technical level."  </p>
<ul>
<li>Translation by Miya Liu.</li>
</ul>
</blockquote>
<p><strong>Testimonial by <a target="_blank" href="https://chinese.freecodecamp.org/news/author/luojiyin/">罗基印 luojiyin</a>:</strong></p>
<blockquote>
<p>我是一名运维开发工程师，通过 freeCodeCamp 学习了有关前端的知识。翻译英文资源，可以接触最新的知识和想法， 提高自己的英文阅读能力和中文的写作能力。也能加快知识的传播，方便别人入门</p>
<p><strong>English Translation:</strong><br>"I'm a DevOps Engineer who has learned about front-end through freeCodeCamp. By translating English resources, I can get access to the latest knowledge and ideas, and improve my English reading and Chinese writing skills. It also speeds up the spreading of knowledge and makes it easier for others to get started."  </p>
<ul>
<li>Translation by Miya Liu.</li>
</ul>
</blockquote>
<h3 id="heading-arabic-testimonial">Arabic Testimonial:</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/03/arabic-blurred.png" alt="Image" width="600" height="400" loading="lazy">
<em>Arabic Testimonial</em></p>
<blockquote>
<p><strong>English Translation:</strong><br>"I've completed 3 certifications on freeCodeCamp's website, and honestly I found it much better than a lot of different curriculums that are being taught in public universities and even expensive private ones, at least where I live. freeCodeCamp was also better than expensive specialized schools."  </p>
<ul>
<li>Translation by Islam Mahfouz.</li>
</ul>
</blockquote>
<h2 id="heading-world-translation-summit-2022">🔹 World Translation Summit 2022</h2>
<p>Now that you know more about our translation effort and the impact that we are having in communities around the world, we have something special for you. </p>
<p>🌐 We would like to invite you to join us for the World Translation Summit. We will have two sessions for different time zones:</p>
<ul>
<li>Friday, April 8 at 9pm EST. </li>
<li>Saturday, April 9 at 9 am EST.</li>
</ul>
<p>📌 It would be awesome if you could be part of our summit. If you are interested in participating, please <a target="_blank" href="https://calendly.com/freecodecamp-org/world-translation-summit-details?month=2022-04">register</a> to receive an invite.</p>
<p>During the summit, you will meet our international staff and you will learn more about our new projects and the progress of our translation effort. We will answer your questions and we will welcome and onboard new volunteers interested in joining our initiative. </p>
<p>By joining our translation effort and our international community, you will be helping people around the world. You will also be making the world a more accessible place where language is no longer a barrier for anyone who wants to learn and thrive through dedication, education, and enthusiasm.</p>
<h3 id="heading-how-to-contribute">How to Contribute</h3>
<p>To join our translation effort:</p>
<p><strong>Step 1:</strong> <a target="_blank" href="https://docs.google.com/forms/d/e/1FAIpQLSdWC609yj1_2afEX0G8AGQyrkGj7bhj1J4XWgCt4BJGuzQk5g/viewform">Fill out this Google form</a>.</p>
<p><strong>Step 2:</strong> <a target="_blank" href="https://discord.gg/PRyKn3Vbay">Join the freeCodeCamp Official Discord</a> and visit the "start-here" room. You can then join a language-specific room and speak your native language.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/06/Cursor_and_start-here_--.png" alt="Cursor_and_start-here_--" width="600" height="400" loading="lazy">
<em>Some of our Discord chatrooms for the global localization effort</em></p>
<p>Note that Discord has a couple of verification steps you will need to complete.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/06/image-107.png" alt="image-107" width="600" height="400" loading="lazy">
<em>If you see this message at the bottom of Discord, click the “complete” button to finish the onboarding process (where you will agree to our community rules).</em></p>
<p>Alternatively, if you just created your Discord account, you might need to wait up to 5 minutes to send messages. (This is an anti-spam counter-measure).</p>
<p>You will receive an email from a Language Lead within a few days to learn a bit more about you and your goals. They may give you access to the freeCodeCamp publication, where you can start translating articles.</p>
<h3 id="heading-thank-you">Thank you</h3>
<p>Finally, we would like to thank our awesome team of volunteers who dedicate their time, knowledge, and energy to our translation effort because everything that we have achieved so far would not have been possible without you. </p>
<p><a target="_blank" href="https://www.freecodecamp.org/news/author/quincylarson/">Quincy Larson</a>, the founder of freeCodeCamp, would like to share this message with all of you:</p>
<blockquote>
<p>"Let's make the world's math, programming, and computer science knowledge available to everyone. With some love and care, we can help people around the world learn in their own native language. This is a team effort by the freeCodeCamp community."</p>
</blockquote>
<p>You are the reason why we are here. We will continue working for you and with you to make sure that education is free and accessible for everyone around the world. </p>
<p>freeCodeCamp has many exciting new projects and ideas, and we welcome you to join our mission. This is just the beginning and we can do this together. </p>
<h2 id="heading-questions-asked-during-the-summit">🔸 Questions Asked During the Summit</h2>
<p>Thank you very much for joining the summit. It was great to see you there. We would like to share with you the answers to the questions that you asked during the event. </p>
<p><strong>What tool can we use to translate freeCodeCamp? Do you have a glossary with technical terms that contributors can refer to?</strong> </p>
<p>The tool that we are using to translate freeCodeCamp is <a target="_blank" href="https://crowdin.com/">Crowdin</a>, a localization management platform. You can learn more about Crowdin and how to contribute to the translation effort in our <a target="_blank" href="https://contribute.freecodecamp.org/#/how-to-translate-files?id=getting-started">Contribution Guidelines</a>.</p>
<p><strong>Do you have any intention/plan to do a WEB 3 and Blockchain Curriculum in the future?</strong></p>
<p>An alumnus is giving us a donation to develop this course. It will not be listed in the main curriculum, but we are creating it because there are many related job positions, and we can teach you the skills you need to apply for these jobs.</p>
<p><strong>How long until freeCodeCamp will start the Bachelor's degree program?</strong></p>
<p>It can take years or even a decade for freeCodeCamp itself to achieve this. But we may be able to work and partner with existing organizations to speed up the process.</p>
<p><strong>Will freeCodeCamp be translated into native languages?</strong></p>
<p>We definitely will if we can find volunteers who want to translate the resources into these languages. As a small nonprofit, we need volunteer contributions to do this. If the curriculum is translated into these languages, we will invest the resources necessary to have the curriculum live.</p>
<p><strong>Why doesn't freeCodeCamp use GitHub and Markdown for the translation effort?</strong></p>
<p>That is a great suggestion. We tried using GitHub in the past and things really started taking off when we started using Crowdin because it can be used by everyone even if they don't have a technical background. Crowdin provides a basic machine translation that can be improved by the translators. We can create a glossary of important terms that appear repeatedly in different files. Our conclusion based on our experience is that Crowdin is a more specialized tool to translate the core curriculum.</p>
<p>We have used GitHub to translate articles for the publications. Every language is experimenting with the tool that works best for the community.</p>
<p><strong>How does freeCodeCamp create the glossary on Crowdin?</strong></p>
<p>We have a repository where we write the list of terms for the glossary, and we upload it to Crowdin. The proofreader team is responsible for making sure that the most accurate translation for the word is being used.</p>
<p><strong>How can I start translating another file without going to the main page on Crowdin?</strong></p>
<p>You can open another file from the file that is being translated. <a target="_blank" href="https://www.freecodecamp.org/news/author/ilenia/">Ilenia Magoni</a> explained this during the event step by step.</p>
<p>If you reach the end of the file there will be a prompt that asks you if you want to go to next file or choose which file to open:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-27.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can also open a different file from the breadcrumb path:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-28.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><img src="https://lh3.googleusercontent.com/EY4cO_a-6FDoaCamzZT1sfK9W7jOz7Kf3G5XnEAQEzLisLhPJ1_a-W7y3xsJaXWInw1v1meZSauHwaTH7nL1EIIq0pKswxy8CNhKsD6PD1-CGiG7s61XlAx7RM4xp9uMCPRoSAHj" alt="Image" width="1065" height="741" loading="lazy"></p>
<p>In the modal to open a new file, you can see which folders and files still have words to translate. This can help you to choose which file to go to next.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-29.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><img src="https://lh4.googleusercontent.com/Dtwfk9cA1-jFhxD5Vi86qUJAC2vaAqDiEnXV2CqJJzzeIlq5mS3ITlVrZjNkzgpSfn-1U5AmKAyZHe4TqEtTq36hqYmADgkvoJsBrk31qL8JgcRJexjjUD90BQ_l2ouCmEgdzlEN" alt="Image" width="1049" height="820" loading="lazy"></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn to Code in Japanese – The Japanese freeCodeCamp Curriculum is Now Live ]]>
                </title>
                <description>
                    <![CDATA[ The Japanese freeCodeCamp curriculum is now live. In Japan, I have seen many comments, tweets, and blog posts saying "freeCodeCamp looks awesome, but unfortunately, I can't use it because I can't read English." Currently, most information and learnin... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-programming-freecodecamp-japanese-released/</link>
                <guid isPermaLink="false">66b0a97a5e73cf343a5cc04e</guid>
                
                    <category>
                        <![CDATA[ freeCodeCamp.org ]]>
                    </category>
                
                    <category>
                        <![CDATA[ internationalization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ localization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ translation ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Yoko Matsuda ]]>
                </dc:creator>
                <pubDate>Thu, 10 Feb 2022 21:06:15 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/02/japanese_certs.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p><a target="_blank" href="https://www.freecodecamp.org/japanese/learn">The Japanese freeCodeCamp curriculum</a> is now live.</p>
<p>In Japan, I have seen many comments, tweets, and blog posts saying "freeCodeCamp looks awesome, but unfortunately, I can't use it because I can't read English."</p>
<p>Currently, most information and learning resources related to programming are in English. But we want freeCodeCamp to be a place where everyone can learn to code in their native language.</p>
<p>I hope the Japanese freeCodeCamp curriculum will be a new option for Japanese speakers who wish to learn to code.</p>
<h2 id="heading-japanese-translation-contributorssupporters">Japanese translation contributors/supporters</h2>
<p>The translation effort at freeCodeCamp is supported by many contributors.</p>
<p>Also, the Japanese translation of the entire curriculum, in particular, was made possible thanks to the support of Mr. Kimio Momose and Mr. Thomas Telandro of the nonprofit organization Unbiased Learning and the translation company TMJ Japan Ltd.</p>
<p>I appreciate all the help from everyone who contributed to this translation effort.</p>
<p>Below is a list of contributors who have participated in the Japanese translation so far.</p>
<h3 id="heading-japanese-translation-contributors">Japanese translation contributors</h3>
<p>yukari-n-erb<br>mmatsumoto1026<br>miya-start<br>tetz-akaneya<br>furidosu<br>Besshy<br>Lulkafe<br>Emi<br>Riokeh<br>King Tony<br>YAMADA Nobuko<br>徳輝方<br>ariadaioh</p>
<p>TMJ Japan Ltd.<br>tomig7<br>Hiroko.Nagayama<br>and others</p>
<p>Supported by: Unbiased Learning</p>
<p>Also, thanks to everyone who gave us kind encouragement in the contributor chat, forum, Twitter, and so on.</p>
<h2 id="heading-frequently-asked-questions">Frequently Asked Questions</h2>
<p>Below are answers to frequently asked questions about the Japanese curriculum.</p>
<h3 id="heading-im-halfway-through-the-english-curriculum-what-should-i-do">I'm halfway through the English curriculum. What should I do?</h3>
<p>Your progress and certificates are available in all languages. You don't have to go over it in Japanese again. You can just switch to the Japanese curriculum (making sure you're signed in) and continue with it.</p>
<p>You can switch languages at any time from the menu button at the top right corner of the <a target="_blank" href="https://www.freecodecamp.org/japanese/learn">learning platform</a>.</p>
<p>Also, certificates you already earned in the past can be displayed in Japanese if you would like.</p>
<h3 id="heading-i-need-help-with-the-curriculum-where-should-i-ask-questions">I need help with the curriculum. Where should I ask questions?</h3>
<p>The <a target="_blank" href="https://forum.freecodecamp.org/">freeCodeCamp forum</a> is the best place to ask questions about the freeCodeCamp curriculum and projects.</p>
<p>In addition, there is now <a target="_blank" href="https://forum.freecodecamp.org/c/japanese/552">Japanese sub-forum</a> too so you can post questions there. Asking questions in Japanese will help other Japanese campers who face the same problem in the future. </p>
<p>Of course, you can also help the Japanese community grow even more by answering questions from other campers.</p>
<h3 id="heading-i-found-a-translation-error-or-i-want-to-propose-improvements-to-a-translation">I found a translation error or I want to propose improvements to a translation.</h3>
<p>We appreciate it if you could let us know in our <a target="_blank" href="https://discord.gg/PRyKn3Vbay">contributor chat</a> or in the comments on Crowdin, our translation platform.</p>
<p>See <a target="_blank" href="https://forum.freecodecamp.org/t/freecodecamp/484083">this forum post</a> for more details.</p>
<p>It's OK even if you are not 100% sure about your suggestion. Please reach out to us, and we can discuss how we can improve it together.</p>
<h3 id="heading-i-want-to-participate-in-the-translation-effort">I want to participate in the translation effort.</h3>
<p>We welcome new contributors! Feel free to join the <a target="_blank" href="https://discord.gg/PRyKn3Vbay">contributor chat</a> and say "Hi".</p>
<p>freeCodeCamp is an open source project, and we are constantly improving and updating our curriculum. New courses will be added from time to time.</p>
<p>Because of this, there will always be more translation work to do each time we add or change something, so we would appreciate your continued contributions.</p>
<p>See below for the information regarding Japanese translation contribution:</p>
<ul>
<li><a target="_blank" href="https://forum.freecodecamp.org/t/freecodecamp/484083">Forum post: freeCodeCamp contribution information in Japanese</a></li>
<li><a target="_blank" href="https://contribute.freecodecamp.org/#/i18n/japanese/index">Contribution guidelines (Japanese)</a></li>
</ul>
<p>You can also contribute to the source code on GitHub.</p>
<h3 id="heading-i-cant-participate-in-translation-but-i-want-to-help-freecodecamp-and-the-japanese-community">I can't participate in translation, but I want to help freeCodeCamp and the Japanese community.</h3>
<p>There will be more and more things we need help with as the Japanese community grows.</p>
<p>Please reach out to me in the <a target="_blank" href="https://discord.gg/PRyKn3Vbay">contributors chat</a>. Let's talk about how we can help the Japanese freeCodeCamp community together.</p>
<p>If you want to learn more about freeCodeCamp, you can read <a target="_blank" href="https://www.freecodecamp.org/japanese/news/about/">other frequently asked questions here</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ World Translation Month – Help Us Translate freeCodeCamp into Your Native Language ]]>
                </title>
                <description>
                    <![CDATA[ We believe that everyone deserves to have free programming education in their own native language. So we are expanding International Translation Day (September 30th) into a full month-long effort. Over the past few years, hundreds of volunteer contri... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/world-translation-month-event/</link>
                <guid isPermaLink="false">66bae5f92c1f85b4545c8bc7</guid>
                
                    <category>
                        <![CDATA[ community ]]>
                    </category>
                
                    <category>
                        <![CDATA[ language ]]>
                    </category>
                
                    <category>
                        <![CDATA[ localization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ translation ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Rafael D. Hernandez ]]>
                </dc:creator>
                <pubDate>Tue, 07 Sep 2021 17:37:37 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2021/09/WTM_BG-yt-1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>We believe that everyone deserves to have free programming education in their own native language. So we are expanding International Translation Day (September 30th) into a full month-long effort.</p>
<p>Over the past few years, hundreds of volunteer contributors have worked to translate freeCodeCamp into major world languages. In February, <a target="_blank" href="https://www.freecodecamp.org/news/world-language-translation-effort/">Quincy announced</a> that freeCodeCamp had successfully launched both Spanish and Chinese editions. And Portuguese and Italian soon followed.</p>
<p>During World Translation Month, we will celebrate what we have achieved collectively – and what we will accomplish for everybody around the world<em>.</em> Watch this one-minute announcement video:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/i2XjBz_U28E" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p><em>If you are interested in participating in translating freeCodeCamp into any world language, you can <a target="_blank" href="https://chat.freecodecamp.org/channel/contributors">visit our contributors channel and learn more</a>.</em></p>
<h2 id="heading-latest-translation-accomplishments">Latest Translation Accomplishments</h2>
<p>Today, we have successfully launched the Italian and Brazilian Portuguese curriculum. We are eager to see what is to come for these active communities.</p>
<p>And the Ukrainian community has really taken off in their translation efforts. They have eight certifications fully translated and two close to 100%, almost all completed within a month. It is remarkable to witness the dedication and perseverance every language community has shown.</p>
<p>We have multiple other communities and individuals who are translating the curriculum to their native languages. You can take a look at the current statuses of all the active translations and their progress here.</p>
<h2 id="heading-current-translation-progress">Current Translation Progress</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td>World Language</td><td>Curriculum %</td><td>Docs %</td></tr>
</thead>
<tbody>
<tr>
<td>Afrikaans</td><td>1%</td><td>59%</td></tr>
<tr>
<td>Arabic</td><td>11%</td><td>29%</td></tr>
<tr>
<td>Azerbaijani</td><td>2%</td><td>1%</td></tr>
<tr>
<td>Bengali</td><td>27%</td><td>1%</td></tr>
<tr>
<td>Catalan</td><td>3%</td><td>1%</td></tr>
<tr>
<td>Chinese</td><td>65%</td><td>56%</td></tr>
<tr>
<td>Czech</td><td>1%</td><td>17%</td></tr>
<tr>
<td>Danish</td><td>1%</td><td>18%</td></tr>
<tr>
<td>Dutch</td><td>4%</td><td>23%</td></tr>
<tr>
<td>Finissh</td><td>1%</td><td>17%</td></tr>
<tr>
<td>French</td><td>20%</td><td>45%</td></tr>
<tr>
<td>German</td><td>31%</td><td>98%</td></tr>
<tr>
<td>Greek</td><td>1%</td><td>1%</td></tr>
<tr>
<td>Hebrew</td><td>1%</td><td>1%</td></tr>
<tr>
<td>Hindi</td><td>1%</td><td>11%</td></tr>
<tr>
<td>Hungarian</td><td>1%</td><td>1%</td></tr>
<tr>
<td>Indonesian</td><td>7%</td><td>30%</td></tr>
<tr>
<td>Italian</td><td>80%</td><td>100%</td></tr>
<tr>
<td>Japanese</td><td>79%</td><td>99%</td></tr>
<tr>
<td>Korean</td><td>1%</td><td>1%</td></tr>
<tr>
<td>Norwegian</td><td>1%</td><td>17%</td></tr>
<tr>
<td>Persian</td><td>12%</td><td>5%</td></tr>
<tr>
<td>Polish</td><td>1%</td><td>19%</td></tr>
<tr>
<td>Portuguese-BR</td><td>79%</td><td>100%</td></tr>
<tr>
<td>Romainian</td><td>48%</td><td>31%</td></tr>
<tr>
<td>Russian</td><td>15%</td><td>95%</td></tr>
<tr>
<td>Spanish</td><td>44%</td><td>84%</td></tr>
<tr>
<td>Swahili</td><td>1%</td><td>1%</td></tr>
<tr>
<td>Swedish</td><td>1%</td><td>19%</td></tr>
<tr>
<td>Tamil</td><td>!%</td><td>34%</td></tr>
<tr>
<td>Telugu</td><td>1%</td><td>4%</td></tr>
<tr>
<td>Turkish</td><td>3%</td><td>4%</td></tr>
<tr>
<td>Ukrainian</td><td>77%</td><td>74%</td></tr>
<tr>
<td>Vietnamese</td><td>1%</td><td>4%</td></tr>
</tbody>
</table>
</div><p>Currently, volunteers around the world are in the process of translating freeCodeCamp's curriculum into 28 world languages.</p>
<p>And many of these world languages are showing significant progress, especially the French, Romanian, Japanese, and German-speaking communities. Keep up the great work!</p>
<h2 id="heading-what-is-the-goal-of-the-world-translation-month-event">What is the Goal of the World Translation Month Event?</h2>
<p>freeCodeCamp's goal is to give every individual the tools to translate the curriculum into their native language. Also, we will dedicate all our efforts and time to this event to reach significant progress for every world language. </p>
<p>We have witnessed what a handful of contributors can do together with a singular purpose. And we hope that World Translation Month will become a yearly event when all world languages can celebrate having access to free programming education translated by their community for their community.</p>
<h2 id="heading-our-reward-system">Our Reward System 🥇</h2>
<p>freeCodeCamp wants to make this a memorable event for every contributor who participates.</p>
<p>During the WTM event, we will give all participants a World Translation Month Badge. Also, at the end of the event, we will present special badges to the Top Translators and Top Proofreaders who have made the most contributions. </p>
<p>You can display these badges on your freeCodeCamp curriculum and forum profiles if you want to do so.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/WTM_Badges.png" alt="Image" width="600" height="400" loading="lazy">
<em>2021 World Translation Month badges</em></p>
<h2 id="heading-the-freecodecamp-localization-roadmap">The freeCodeCamp Localization Roadmap</h2>
<p>The freeCodeCamp curriculum is already available in Chinese and Spanish. And beyond this, these communities have many other resources at their disposal, thanks to the efforts of hundreds of contributors.</p>
<p>For example, the Chinese-speaking community has translated nearly all the certifications into Chinese. They also have close to 600 articles translated, there are 10 of freeCodeCamp's video tutorials with subtitles on <a target="_blank" href="https://space.bilibili.com/335505768/video">Bilibili</a>, and they've organized hundreds of meetups, hackathons, conferences, live coding events, and coding workshops in universities and high schools.</p>
<p><img src="https://chinese.freecodecamp.org/news/content/images/2021/09/image-1.png" alt="Image" width="913" height="557" loading="lazy">
<em>freeCodeCamp bilibili 频道</em></p>
<p>The Spanish-speaking community has the first two certifications available in Spanish, and they've translated around 250 articles. Community members have also written about 20 original articles, created 3 original full-length video tutorials, and <a target="_blank" href="https://www.freecodecamp.org/news/p/fc63f178-c627-414a-8ae6-877eb3458261/@EstefaniaCassN">Estefania</a> has created 24 short videos for the Spanish YouTube channel. </p>
<p>The response from the Spanish-speaking community has been remarkable on <a target="_blank" href="https://www.youtube.com/c/freeCodeCampEspa%C3%B1ol/videos">YouTube</a> and <a target="_blank" href="https://twitter.com/freecodecampES">Twitter</a>. Thanks to the fantastic job Estefania has been doing by engaging with the community with posts and short videos on YouTube, the channel now has over 12,000 followers. And freeCodeCamp's Twitter account en Español has reached 7,300 followers while continuing to grow.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/Screen-Shot-2021-09-06-at-2.23.41-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>YouTube Channel freeCodeCamp en Español</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/09/Screen-Shot-2021-09-06-at-2.29.17-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Twitter freeCodeCamp en Español</em></p>
<h2 id="heading-the-translation-blueprint">The Translation Blueprint</h2>
<p>As Quincy mentioned in the <a target="_blank" href="https://www.freecodecamp.org/news/world-language-translation-effort/">World Language Translation Effort</a> article, freeCodeCamp's "<em>...long-term goal is for each of these language communities to come into its own.</em>" </p>
<p>And we'll take the same steps as we took with the thriving Spanish-speaking and Chinese-speaking communities with other language communities around the world. </p>
<p>The plan is to launch a localized publication, YouTube Channel, sub-forum, and Twitter account for these language communities, each with their own contributors and staff.</p>
<h2 id="heading-thank-you-to-all-the-translators-contributors-and-proofreaders">Thank You to All the Translators, Contributors, and Proofreaders!</h2>
<p>I want to finish up by thanking the proofreaders and translators who have dedicated hours upon hours to translating and proofreading. </p>
<h3 id="heading-active-translators">Active Translators</h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>World Language</td><td>Translated Strings</td></tr>
</thead>
<tbody>
<tr>
<td>Aziz Meknassi</td><td>Arabic</td><td>4</td></tr>
<tr>
<td>Damani Salah Eddin</td><td>Arabic</td><td>18</td></tr>
<tr>
<td>elmadhdi1962</td><td>Arabic</td><td>4</td></tr>
<tr>
<td>fatima</td><td>Arabic</td><td>2</td></tr>
<tr>
<td>Gehad Salem</td><td>Arabic</td><td>11</td></tr>
<tr>
<td>Khalid Benjelloun</td><td>Arabic</td><td>3</td></tr>
<tr>
<td>Rundi Wadi</td><td>Arabic</td><td>38</td></tr>
<tr>
<td>Modasser Billah</td><td>Bengali</td><td>5</td></tr>
<tr>
<td>nr072</td><td>Bengali</td><td>77</td></tr>
<tr>
<td>Pabitra Jana</td><td>Bengali</td><td>1</td></tr>
<tr>
<td>Raihan Mahmud</td><td>Bengali</td><td>70</td></tr>
<tr>
<td>Salman Shuvo</td><td>Bengali</td><td>47</td></tr>
<tr>
<td>Chengjun.L</td><td>Chinese</td><td>49</td></tr>
<tr>
<td>cocoder</td><td>Chinese</td><td>26</td></tr>
<tr>
<td>Simon Yang</td><td>Chinese</td><td>1</td></tr>
<tr>
<td>xhksun</td><td>Chinese</td><td>166</td></tr>
<tr>
<td>ztftrue</td><td>Chinese</td><td>1</td></tr>
<tr>
<td>Hana Klingová</td><td>Czech</td><td>28</td></tr>
<tr>
<td>johmar</td><td>Dutch</td><td>339</td></tr>
<tr>
<td>cbnrd</td><td>French</td><td>43</td></tr>
<tr>
<td>David Heusler</td><td>French</td><td>109</td></tr>
<tr>
<td>Flo</td><td>French</td><td>1</td></tr>
<tr>
<td>Julien Li</td><td>French</td><td>449</td></tr>
<tr>
<td>Mariefay</td><td>French</td><td>14</td></tr>
<tr>
<td>MNE</td><td>French</td><td>29</td></tr>
<tr>
<td>Rémy Beumier</td><td>French</td><td>1</td></tr>
<tr>
<td>srasay2</td><td>French</td><td>1</td></tr>
<tr>
<td>Andrew Russell</td><td>German</td><td>28</td></tr>
<tr>
<td>AW</td><td>German</td><td>84</td></tr>
<tr>
<td>Julia Wegmayr</td><td>German</td><td>248</td></tr>
<tr>
<td>Martin Seibert</td><td>German</td><td>1</td></tr>
<tr>
<td>Philipp R. Proksch</td><td>German</td><td>3</td></tr>
<tr>
<td>Philipp S</td><td>German</td><td>312</td></tr>
<tr>
<td>Vairus</td><td>Greek</td><td>10</td></tr>
<tr>
<td>Jod Louis</td><td>Haitian Creole</td><td>1</td></tr>
<tr>
<td>Ami</td><td>Hebrew</td><td>28</td></tr>
<tr>
<td>bachdor24</td><td>Hebrew</td><td>4</td></tr>
<tr>
<td>Curiosity_17</td><td>Hindi</td><td>1</td></tr>
<tr>
<td>Japmohan kumar</td><td>Hindi</td><td>1</td></tr>
<tr>
<td>adh</td><td>Indonesian</td><td>299</td></tr>
<tr>
<td>Arief Darmawan</td><td>Indonesian</td><td>503</td></tr>
<tr>
<td>Danang Aprias Noor Fadilla</td><td>Indonesian</td><td>46</td></tr>
<tr>
<td>Dicky Giancini</td><td>Indonesian</td><td>94</td></tr>
<tr>
<td>Dyah Achwatiningrum</td><td>Indonesian</td><td>368</td></tr>
<tr>
<td>Fahmi Aditia</td><td>Indonesian</td><td>50</td></tr>
<tr>
<td>Hendra Bangun Dwi R</td><td>Indonesian</td><td>8</td></tr>
<tr>
<td>Rifqi</td><td>Indonesian</td><td>1</td></tr>
<tr>
<td>Tjandra Darmo</td><td>Indonesian</td><td>6</td></tr>
<tr>
<td>wardhen</td><td>Indonesian</td><td>115</td></tr>
<tr>
<td>iuri86</td><td>Italian</td><td>10</td></tr>
<tr>
<td>TOMMASO DI COSTANZO</td><td>Italian</td><td>35</td></tr>
<tr>
<td>Emi</td><td>Japanese</td><td>7</td></tr>
<tr>
<td>Julie Park</td><td>Korean</td><td>19</td></tr>
<tr>
<td>San</td><td>Korean</td><td>9</td></tr>
<tr>
<td>Sewook Han</td><td>Korean</td><td>6</td></tr>
<tr>
<td>Zergro</td><td>Norwegian</td><td>3</td></tr>
<tr>
<td>m_golzar</td><td>Persian</td><td>8</td></tr>
<tr>
<td>najme</td><td>Persian</td><td>571</td></tr>
<tr>
<td>Jakub Siwik</td><td>Polish</td><td>27</td></tr>
<tr>
<td>BrainMath</td><td>Portuguese, Brazilian</td><td>10</td></tr>
<tr>
<td>Clovis Goulart</td><td>Portuguese, Brazilian</td><td>340</td></tr>
<tr>
<td>Cássio Barth</td><td>Portuguese, Brazilian</td><td>1</td></tr>
<tr>
<td>fcc_javascript_4linux</td><td>Portuguese, Brazilian</td><td>1</td></tr>
<tr>
<td>Felipe Santos</td><td>Portuguese, Brazilian</td><td>8</td></tr>
<tr>
<td>Isabella Lima</td><td>Portuguese, Brazilian</td><td>3</td></tr>
<tr>
<td>Jualianaluzia</td><td>Portuguese, Brazilian</td><td>36</td></tr>
<tr>
<td>Lais Golin</td><td>Portuguese, Brazilian</td><td>1</td></tr>
<tr>
<td>luforain</td><td>Portuguese, Brazilian</td><td>1</td></tr>
<tr>
<td>Rick</td><td>Portuguese, Brazilian</td><td>2</td></tr>
<tr>
<td>Silvano RM</td><td>Portuguese, Brazilian</td><td>17</td></tr>
<tr>
<td>Clovis Goulart</td><td>Portuguese, Portugal</td><td>37</td></tr>
<tr>
<td>Pedro Goncalves</td><td>Portuguese, Portugal</td><td>65</td></tr>
<tr>
<td>Ghenadie Tofan</td><td>Romanian</td><td>422</td></tr>
<tr>
<td>Alexander Filëv</td><td>Russian</td><td>114</td></tr>
<tr>
<td>Beloze</td><td>Russian</td><td>26</td></tr>
<tr>
<td>Cherepnin</td><td>Russian</td><td>97</td></tr>
<tr>
<td>Corrector</td><td>Russian</td><td>87</td></tr>
<tr>
<td>Farid</td><td>Russian</td><td>2</td></tr>
<tr>
<td>Helge Kim</td><td>Russian</td><td>5</td></tr>
<tr>
<td>Knopentiya</td><td>Russian</td><td>3</td></tr>
<tr>
<td>Pavel Ryazantsev</td><td>Russian</td><td>7</td></tr>
<tr>
<td>Rita Shinger</td><td>Russian</td><td>25</td></tr>
<tr>
<td>vekotov</td><td>Russian</td><td>28</td></tr>
<tr>
<td>Виктор Сударинен</td><td>Russian</td><td>1</td></tr>
<tr>
<td>Тимофей Рассолов</td><td>Russian</td><td>198</td></tr>
<tr>
<td>daca</td><td>Serbian</td><td>6</td></tr>
<tr>
<td>Abel Campos</td><td>Spanish</td><td>13</td></tr>
<tr>
<td>Aldair Avalos</td><td>Spanish</td><td>86</td></tr>
<tr>
<td>Alvaro Agamez</td><td>Spanish</td><td>159</td></tr>
<tr>
<td>Andres</td><td>Spanish</td><td>2</td></tr>
<tr>
<td>Atilio Garcia Pezo</td><td>Spanish</td><td>4</td></tr>
<tr>
<td>Christian Caracach</td><td>Spanish</td><td>13</td></tr>
<tr>
<td>DavitBoo</td><td>Spanish</td><td>1</td></tr>
<tr>
<td>devsiderio</td><td>Spanish</td><td>23</td></tr>
<tr>
<td>Drifting Live</td><td>Spanish</td><td>1</td></tr>
<tr>
<td>Erik</td><td>Spanish</td><td>4</td></tr>
<tr>
<td>Hernan David Cuy Salcedo</td><td>Spanish</td><td>20</td></tr>
<tr>
<td>Javier Coronado Velasquez</td><td>Spanish</td><td>377</td></tr>
<tr>
<td>JorgeT</td><td>Spanish</td><td>2</td></tr>
<tr>
<td>Karlos Arroyo Fernandez</td><td>Spanish</td><td>8</td></tr>
<tr>
<td>Laura</td><td>Spanish</td><td>1</td></tr>
<tr>
<td>Luis Carlos Figueroa Veliz</td><td>Spanish</td><td>10</td></tr>
<tr>
<td>Marco Segura</td><td>Spanish</td><td>5</td></tr>
<tr>
<td>Mariano Esquivel</td><td>Spanish</td><td>20</td></tr>
<tr>
<td>Martin Diaz</td><td>Spanish</td><td>1</td></tr>
<tr>
<td>Maximiliano Romero</td><td>Spanish</td><td>4</td></tr>
<tr>
<td>Nestor Plasencia</td><td>Spanish</td><td>1</td></tr>
<tr>
<td>Renzo-Chong</td><td>Spanish</td><td>2</td></tr>
<tr>
<td>Rumen Zaechki</td><td>Spanish</td><td>6</td></tr>
<tr>
<td>Santiago Correa Alvarez</td><td>Spanish</td><td>18</td></tr>
<tr>
<td>Sergio Fdez</td><td>Spanish</td><td>21</td></tr>
<tr>
<td>Sofiapicco</td><td>Spanish</td><td>2</td></tr>
<tr>
<td>Ulises Lopez</td><td>Spanish</td><td>12</td></tr>
<tr>
<td>Chaandha Raghav</td><td>Tamil</td><td>128</td></tr>
<tr>
<td>Raviraj Subramanian</td><td>Tamil</td><td>7</td></tr>
<tr>
<td>Eren Byxlarge</td><td>Turkish</td><td>8</td></tr>
<tr>
<td>Kubilaycitak</td><td>Turkish</td><td>18</td></tr>
<tr>
<td>Mehmet Emin Eraslan</td><td>Turkish</td><td>2</td></tr>
<tr>
<td>Alina Bovsunivska</td><td>Ukrainian</td><td>217</td></tr>
<tr>
<td>alina_farafonova</td><td>Ukrainian</td><td>15</td></tr>
<tr>
<td>alx<em>man</em></td><td>Ukrainian</td><td>122</td></tr>
<tr>
<td>Anastasia Trius</td><td>Ukrainian</td><td>304</td></tr>
<tr>
<td>Anastasia_k</td><td>Ukrainian</td><td>131</td></tr>
<tr>
<td>andrii.bodnar</td><td>Ukrainian</td><td>2</td></tr>
<tr>
<td>Angelina Yaremchuk</td><td>Ukrainian</td><td>242</td></tr>
<tr>
<td>Anna Verbytska</td><td>Ukrainian</td><td>183</td></tr>
<tr>
<td>anna.linevych</td><td>Ukrainian</td><td>106</td></tr>
<tr>
<td>anya_filipchuk</td><td>Ukrainian</td><td>1</td></tr>
<tr>
<td>coolakova</td><td>Ukrainian</td><td>185</td></tr>
<tr>
<td>Cофія Назарчук</td><td>Ukrainian</td><td>199</td></tr>
<tr>
<td>Daria Deinekina</td><td>Ukrainian</td><td>156</td></tr>
<tr>
<td>Darina Gorichenko</td><td>Ukrainian</td><td>373</td></tr>
<tr>
<td>DarinaMilova</td><td>Ukrainian</td><td>168</td></tr>
<tr>
<td>Daryna</td><td>Ukrainian</td><td>270</td></tr>
<tr>
<td>Diana</td><td>Ukrainian</td><td>169</td></tr>
<tr>
<td>Dmytro Zubenko</td><td>Ukrainian</td><td>534</td></tr>
<tr>
<td>Doctorplague</td><td>Ukrainian</td><td>110</td></tr>
<tr>
<td>Inga Usenko</td><td>Ukrainian</td><td>1</td></tr>
<tr>
<td>Iryna Lobko</td><td>Ukrainian</td><td>212</td></tr>
<tr>
<td>Ivan Adamchuk</td><td>Ukrainian</td><td>366</td></tr>
<tr>
<td>Ivanka_Kvasna</td><td>Ukrainian</td><td>202</td></tr>
<tr>
<td>Julia Serbinenko</td><td>Ukrainian</td><td>283</td></tr>
<tr>
<td>K_Katrina_A</td><td>Ukrainian</td><td>36</td></tr>
<tr>
<td>Kateryna_sk</td><td>Ukrainian</td><td>410</td></tr>
<tr>
<td>Katya Belikova</td><td>Ukrainian</td><td>190</td></tr>
<tr>
<td>Khristina Konvaliuk</td><td>Ukrainian</td><td>91</td></tr>
<tr>
<td>Liubov Kot</td><td>Ukrainian</td><td>9</td></tr>
<tr>
<td>Maria Gaidarzhy</td><td>Ukrainian</td><td>162</td></tr>
<tr>
<td>Mariana Minko</td><td>Ukrainian</td><td>319</td></tr>
<tr>
<td>Maryna Moroz</td><td>Ukrainian</td><td>124</td></tr>
<tr>
<td>minkaffe</td><td>Ukrainian</td><td>262</td></tr>
<tr>
<td>Nata</td><td>Ukrainian</td><td>143</td></tr>
<tr>
<td>Nataliia Mykolyshyn4</td><td>Ukrainian</td><td>314</td></tr>
<tr>
<td>nathuzovata</td><td>Ukrainian</td><td>257</td></tr>
<tr>
<td>ol_kvasna</td><td>Ukrainian</td><td>198</td></tr>
<tr>
<td>Olena Tyshkevych</td><td>Ukrainian</td><td>321</td></tr>
<tr>
<td>olena.karpina</td><td>Ukrainian</td><td>209</td></tr>
<tr>
<td>olia-k</td><td>Ukrainian</td><td>228</td></tr>
<tr>
<td>Pavlo Tiupa</td><td>Ukrainian</td><td>320</td></tr>
<tr>
<td>Roksolana Khanas</td><td>Ukrainian</td><td>313</td></tr>
<tr>
<td>Solomia2108 Kotiai</td><td>Ukrainian</td><td>330</td></tr>
<tr>
<td>Solomiia Stupak</td><td>Ukrainian</td><td>228</td></tr>
<tr>
<td>SOPHIE_20861</td><td>Ukrainian</td><td>17</td></tr>
<tr>
<td>Sophiya</td><td>Ukrainian</td><td>349</td></tr>
<tr>
<td>tetiana_kinashchuk</td><td>Ukrainian</td><td>272</td></tr>
<tr>
<td>vdenyssko</td><td>Ukrainian</td><td>164</td></tr>
<tr>
<td>Viktoriia Farenyk</td><td>Ukrainian</td><td>353</td></tr>
<tr>
<td>Viktoriia_Shoptenko</td><td>Ukrainian</td><td>79</td></tr>
<tr>
<td>vitka-kvitka</td><td>Ukrainian</td><td>199</td></tr>
<tr>
<td>Yaroslav Stryhun</td><td>Ukrainian</td><td>291</td></tr>
<tr>
<td>yulialutsenko</td><td>Ukrainian</td><td>2</td></tr>
<tr>
<td>Zhandm</td><td>Ukrainian</td><td>26</td></tr>
<tr>
<td>Аліна Соловій</td><td>Ukrainian</td><td>334</td></tr>
<tr>
<td>Андрій Андрійович Сукнацький</td><td>Ukrainian</td><td>271</td></tr>
<tr>
<td>Андрій Біленко</td><td>Ukrainian</td><td>275</td></tr>
<tr>
<td>Богдана Вознюк</td><td>Ukrainian</td><td>6</td></tr>
<tr>
<td>Вікторія Мельник</td><td>Ukrainian</td><td>145</td></tr>
<tr>
<td>Дарія Фадєєва</td><td>Ukrainian</td><td>210</td></tr>
<tr>
<td>Кристина Єщенко</td><td>Ukrainian</td><td>59</td></tr>
<tr>
<td>Таня Щадило</td><td>Ukrainian</td><td>339</td></tr>
<tr>
<td>Тимофей Рассолов</td><td>Ukrainian</td><td>1</td></tr>
<tr>
<td>Тоня Маркиш</td><td>Ukrainian</td><td>98</td></tr>
<tr>
<td>Ілона Єщенко</td><td>Ukrainian</td><td>67</td></tr>
<tr>
<td>Anushah Nadir</td><td>Urdu</td><td>17</td></tr>
<tr>
<td>Muhammad Ali</td><td>Urdu</td><td>54</td></tr>
<tr>
<td>Sharaf A</td><td>Urdu</td><td>12</td></tr>
</tbody>
</table>
</div><h3 id="heading-active-proofreaders">Active Proofreaders</h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Name</td><td>World Language</td><td>Translated Strings</td><td>Approved Strings</td></tr>
</thead>
<tbody>
<tr>
<td>Miya Liu</td><td>Chinese</td><td>18</td><td>2547</td></tr>
<tr>
<td>Alan Luo</td><td>Chinese</td><td>567</td><td>480</td></tr>
<tr>
<td>Christophe Thomas</td><td>French</td><td>537</td><td>372</td></tr>
<tr>
<td>Gaelle Tjat</td><td>French</td><td>572</td><td>1492</td></tr>
<tr>
<td>Stephan Düsterhöft</td><td>German</td><td>1070</td><td>1144</td></tr>
<tr>
<td>Michaelsndr</td><td>German</td><td>586</td><td>809</td></tr>
<tr>
<td>Dicky Giancini</td><td>Indonesian</td><td>83</td><td>492</td></tr>
<tr>
<td>Andrea Ros</td><td>Italian</td><td>875</td><td>52</td></tr>
<tr>
<td>Ilenia Magoni</td><td>Italian</td><td>405</td><td>18</td></tr>
<tr>
<td>alevanni19</td><td>Italian</td><td>11</td><td></td></tr>
<tr>
<td>sidemt</td><td>Japanese</td><td>162</td><td>175</td></tr>
<tr>
<td>Daniel Rosa</td><td>Portuguese, Brazil</td><td>1427</td><td>1839</td></tr>
<tr>
<td>Ricardo Passos</td><td>Portuguese, Brazil</td><td>77</td><td></td></tr>
<tr>
<td>fcc_javascript_4linux</td><td>Portuguese, Brazil</td><td>1</td><td></td></tr>
<tr>
<td>Sam_3877</td><td>Romanian</td><td>1696</td><td></td></tr>
<tr>
<td>Juan Carrillo</td><td>Spanish</td><td>241</td><td>1951</td></tr>
<tr>
<td>choidavid4</td><td>Spanish</td><td>357</td><td>349</td></tr>
<tr>
<td>Bohdana Vozniuk</td><td>Ukrainian</td><td>103</td><td>137</td></tr>
</tbody>
</table>
</div><p>Also, thank you to all the proofreaders and participants in the World Translation Month video:</p>
<ul>
<li>Andrea Ros - Italian Proofreader</li>
<li><a target="_blank" href="https://twitter.com/Daniel__Rosa">Daniel Rosa</a> - Portuguese-BR Proofreader</li>
<li><a target="_blank" href="https://twitter.com/stephandue">Stephan Düsterhöft</a> and Michael Franz - German Proofreaders</li>
<li><a target="_blank" href="https://twitter.com/sideyoks">Sidemt (Yoko)</a> - Japanese Proofreader</li>
<li>Adina Solomon - Romanian Proofreader</li>
<li>Khalid - Arabic Proofreader</li>
<li><a target="_blank" href="https://twitter.com/juancarrillofl">Juan Carrillo</a> - Spanish Proofreader</li>
<li><a target="_blank" href="https://github.com/S1ngS1ng">S1ng S1ng</a>，<a target="_blank" href="https://github.com/iLtc">Alan Luo</a>，<a target="_blank" href="https://github.com/ZhichengChen">Zhicheng Chen</a>，<a target="_blank" href="https://github.com/zhannicholas">Nicholas Zhan</a>，<a target="_blank" href="https://twitter.com/miyaliu666">Miya Liu</a> - Translators/Proofreaders</li>
</ul>
<p><em>If you are interested in participating in translating freeCodeCamp's curriculum into any world language, you can <a target="_blank" href="https://chat.freecodecamp.org/channel/contributors">visit our contributors channel and learn more</a>.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Create a Multi-Language Translator Using Blazor and Azure Cognitive Services ]]>
                </title>
                <description>
                    <![CDATA[ By Ankit Sharma Introduction In this article, we will create a multilanguage translator using Blazor and the Translate Text Azure Cognitive Service.  This translator will be able to translate between all the languages supported by the Translate Text ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-create-a-multi-language-translator-using-blazor-and-azure-cognitive-services/</link>
                <guid isPermaLink="false">66d45da23dce891ac3a967ae</guid>
                
                    <category>
                        <![CDATA[ Aspnetcore ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Azure ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Blazor ]]>
                    </category>
                
                    <category>
                        <![CDATA[ translation ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 09 Mar 2020 14:14:00 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9c3b740569d1a4ca30de.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Ankit Sharma</p>
<h2 id="heading-introduction">Introduction</h2>
<p>In this article, we will create a multilanguage translator using Blazor and the Translate Text Azure Cognitive Service. </p>
<p>This translator will be able to translate between all the languages supported by the Translate Text API. Currently, the Translate Text API supports more than 60 languages for translation. </p>
<p>The application will accept the text to translate and the target language as the input and returns the translated text and the detected language for the input text as the output.</p>
<p>Take a look at the output shown below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/BlazorTranslator.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<ul>
<li>Install the latest .NET Core 3.1 SDK from <a target="_blank" href="https://dotnet.microsoft.com/download/dotnet-core/3.1">https://dotnet.microsoft.com/download/dotnet-core/3.1</a></li>
<li>Install the latest version of Visual Studio 2019 from <a target="_blank" href="https://visualstudio.microsoft.com/downloads/">https://visualstudio.microsoft.com/downloads/</a></li>
<li>An Azure subscription account. You can create a free Azure account at <a target="_blank" href="https://azure.microsoft.com/en-in/free/">https://azure.microsoft.com/en-in/free/</a></li>
</ul>
<h2 id="heading-source-code">Source Code</h2>
<p>You can get the source code from <a target="_blank" href="https://github.com/AnkitSharma-007/Blazor-Translator-Azure-Cognitive-Services">GitHub</a>.</p>
<h2 id="heading-create-the-azure-translator-text-cognitive-services-resource">Create the Azure Translator Text Cognitive Services resource</h2>
<p>Log in to the Azure portal and search for the cognitive services in the search bar and click on the result. Refer to the image shown below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/CreateTextCogServ-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>On the next screen, click on the <code>Add</code> button. It will open the cognitive services marketplace page. Search for the <code>Translator Text</code> in the search bar and click on the search result. It will open the Translator Text API page. Click on the <code>Create</code> button to create a new Translator Text resource. Refer to the image shown below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/SelectTranslatorTextCogServ.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>On the <code>Create</code> page, fill in the details as indicated below.</p>
<ul>
<li>Name: Give a unique name for your resource.</li>
<li>Subscription: Select the subscription type from the dropdown.</li>
<li>Pricing tier: Select the pricing tier as per your choice.</li>
<li>Resource group: Select an existing resource group or create a new one.</li>
</ul>
<p>Click on the <code>Create</code> button. Refer to the image shown below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/ConfigureTranslatorTextCogServ.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>After your resource is successfully deployed, click on the “Go to resource” button. You can see the Key and the endpoint for the newly created Translator Text resource. Refer to the image shown below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/TextCogServKey.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Make a note of the key, as we will be using this in the latter part of this article to request the translations from the Translator Text API. The values are masked here for privacy.</p>
<h2 id="heading-create-a-server-side-blazor-application">Create a Server-Side Blazor Application</h2>
<p>Open Visual Studio 2019 and click on “Create a new project”. Select “Blazor App” and click on the “Next” button. Refer to the image shown below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/CreateProject-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>On the next window, put the project name as <code>BlazorTranslator</code> and click on the “Create” button. The next window will ask you to select the type of Blazor app. Select <code>Blazor Server App</code> and click on the Create button to create a new server-side Blazor application. Refer to the image shown below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/BlazorTemplate-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-creating-the-models">Creating the Models</h2>
<p>Right-click on <code>BlazorTranslator</code> project and select Add &gt;&gt; New Folder. Name the folder as Models. Again, right-click on the Models folder and select Add &gt;&gt; Class to add a new class file. Put the name of your class as <code>LanguageDetails.cs</code> and click Add.</p>
<p>Open <code>[LanguageDetails.cs](https://github.com/AnkitSharma-007/Blazor-Translator-Azure-Cognitive-Services/blob/master/BlazorTranslator/Models/LanguageDetails.cs)</code> and put the following code inside it.</p>
<pre><code class="lang-c#"><span class="hljs-keyword">namespace</span> <span class="hljs-title">BlazorTranslator.Models</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">LanguageDetails</span>
    {
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Name { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> NativeName { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Dir { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    }
}
</code></pre>
<p>Similarly, add a new class file <code>[TextResult.cs](https://github.com/AnkitSharma-007/Blazor-Translator-Azure-Cognitive-Services/blob/master/BlazorTranslator/Models/TextResult.cs)</code> and put the following code inside it.</p>
<pre><code class="lang-c#"><span class="hljs-keyword">using</span> System;
<span class="hljs-keyword">namespace</span> <span class="hljs-title">BlazorTranslator.Models</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">TextResult</span>
    {
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Text { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Script { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    }
}
</code></pre>
<p>Add a new class file <code>[Translation.cs](https://github.com/AnkitSharma-007/Blazor-Translator-Azure-Cognitive-Services/blob/master/BlazorTranslator/Models/Translation.cs)</code> and put the following code inside it.</p>
<pre><code class="lang-c#"><span class="hljs-keyword">namespace</span> <span class="hljs-title">BlazorTranslator.Models</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Translation</span>
    {
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Text { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
        <span class="hljs-keyword">public</span> TextResult Transliteration { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> To { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    }
}
</code></pre>
<p>Create a class file <code>[DetectedLanguage.cs](https://github.com/AnkitSharma-007/Blazor-Translator-Azure-Cognitive-Services/blob/master/BlazorTranslator/Models/DetectedLanguage.cs)</code> and put the following code inside it.</p>
<pre><code class="lang-c#"><span class="hljs-keyword">namespace</span> <span class="hljs-title">BlazorTranslator.Models</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">DetectedLanguage</span>
    {
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Language { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">float</span> Score { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    }
}
</code></pre>
<p>Create a class file <code>[TranslationResult.cs](https://github.com/AnkitSharma-007/Blazor-Translator-Azure-Cognitive-Services/blob/master/BlazorTranslator/Models/TranslationResult.cs)</code> and put the following code inside it.</p>
<pre><code class="lang-c#"><span class="hljs-keyword">namespace</span> <span class="hljs-title">BlazorTranslator.Models</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">TranslationResult</span>
    {
        <span class="hljs-keyword">public</span> DetectedLanguage DetectedLanguage { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
        <span class="hljs-keyword">public</span> TextResult SourceText { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
        <span class="hljs-keyword">public</span> Translation[] Translations { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    }
}
</code></pre>
<p>Finally, create the class file <code>[AvailableLanguage.cs](https://github.com/AnkitSharma-007/Blazor-Translator-Azure-Cognitive-Services/blob/master/BlazorTranslator/Models/AvailableLanguage.cs)</code> and put the following code inside it.</p>
<pre><code class="lang-c#"><span class="hljs-keyword">using</span> System.Collections.Generic;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">BlazorTranslator.Models</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">AvailableLanguage</span>
    {
      <span class="hljs-keyword">public</span> Dictionary&lt;<span class="hljs-keyword">string</span>, LanguageDetails&gt; Translation { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    }
}
</code></pre>
<h2 id="heading-create-the-translation-service">Create the Translation service</h2>
<p>Right-click on the <code>BlazorTranslator/Data</code> folder and select Add &gt;&gt; Class to add a new class file. Put the name of the file as <code>TranslationService.cs</code> and click on Add. Open <code>[TranslationService.cs](https://github.com/AnkitSharma-007/Blazor-Translator-Azure-Cognitive-Services/blob/master/BlazorTranslator/Data/TranslationService.cs)</code> file and put the following code inside it.</p>
<pre><code class="lang-c#"><span class="hljs-keyword">using</span> BlazorTranslator.Models;
<span class="hljs-keyword">using</span> Newtonsoft.Json;
<span class="hljs-keyword">using</span> System;
<span class="hljs-keyword">using</span> System.Net.Http;
<span class="hljs-keyword">using</span> System.Text;
<span class="hljs-keyword">using</span> System.Threading.Tasks;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">BlazorTranslator.Data</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">TranslationService</span>
    {
        <span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;TranslationResult[]&gt; GetTranslatation(<span class="hljs-keyword">string</span> textToTranslate, <span class="hljs-keyword">string</span> targetLanguage)
        {
            <span class="hljs-keyword">string</span> subscriptionKey = <span class="hljs-string">"af19d996a3cb4a70a808567aad5bc41a"</span>;
            <span class="hljs-keyword">string</span> apiEndpoint = <span class="hljs-string">"https://api.cognitive.microsofttranslator.com/"</span>;
            <span class="hljs-keyword">string</span> route = <span class="hljs-string">$"/translate?api-version=3.0&amp;to=<span class="hljs-subst">{targetLanguage}</span>"</span>;
            <span class="hljs-keyword">string</span> requestUri = apiEndpoint + route;
            TranslationResult[] translationResult = <span class="hljs-keyword">await</span> TranslateText(subscriptionKey, requestUri, textToTranslate);
            <span class="hljs-keyword">return</span> translationResult;
        }

        <span class="hljs-keyword">async</span> Task&lt;TranslationResult[]&gt; TranslateText(<span class="hljs-keyword">string</span> subscriptionKey, <span class="hljs-keyword">string</span> requestUri, <span class="hljs-keyword">string</span> inputText)
        {
            <span class="hljs-keyword">object</span>[] body = <span class="hljs-keyword">new</span> <span class="hljs-keyword">object</span>[] { <span class="hljs-keyword">new</span> { Text = inputText } };
            <span class="hljs-keyword">var</span> requestBody = JsonConvert.SerializeObject(body);

            <span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> client = <span class="hljs-keyword">new</span> HttpClient())
            <span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> request = <span class="hljs-keyword">new</span> HttpRequestMessage())
            {
                request.Method = HttpMethod.Post;
                request.RequestUri = <span class="hljs-keyword">new</span> Uri(requestUri);
                request.Content = <span class="hljs-keyword">new</span> StringContent(requestBody, Encoding.UTF8, <span class="hljs-string">"application/json"</span>);
                request.Headers.Add(<span class="hljs-string">"Ocp-Apim-Subscription-Key"</span>, subscriptionKey);

                HttpResponseMessage response = <span class="hljs-keyword">await</span> client.SendAsync(request).ConfigureAwait(<span class="hljs-literal">false</span>);
                <span class="hljs-keyword">string</span> result = <span class="hljs-keyword">await</span> response.Content.ReadAsStringAsync();
                TranslationResult[] deserializedOutput = JsonConvert.DeserializeObject&lt;TranslationResult[]&gt;(result);

                <span class="hljs-keyword">return</span> deserializedOutput;
            }
        }

        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;AvailableLanguage&gt; <span class="hljs-title">GetAvailableLanguages</span>(<span class="hljs-params"></span>)</span>
        {
            <span class="hljs-keyword">string</span> endpoint = <span class="hljs-string">"https://api.cognitive.microsofttranslator.com/languages?api-version=3.0&amp;scope=translation"</span>;
            <span class="hljs-keyword">var</span> client = <span class="hljs-keyword">new</span> HttpClient();
            <span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> request = <span class="hljs-keyword">new</span> HttpRequestMessage())
            {
                request.Method = HttpMethod.Get;
                request.RequestUri = <span class="hljs-keyword">new</span> Uri(endpoint);
                <span class="hljs-keyword">var</span> response = <span class="hljs-keyword">await</span> client.SendAsync(request).ConfigureAwait(<span class="hljs-literal">false</span>);
                <span class="hljs-keyword">string</span> result = <span class="hljs-keyword">await</span> response.Content.ReadAsStringAsync();

                AvailableLanguage deserializedOutput = JsonConvert.DeserializeObject&lt;AvailableLanguage&gt;(result);

                <span class="hljs-keyword">return</span> deserializedOutput;
            }
        }
    }
}
</code></pre>
<p>We have defined a <code>GetTranslatation</code> method which will accept two parameters – the text to translate and the target language. We will set the subscription key for the Azure Translator Text cognitive service and define a variable for the global endpoint for Translator Text. The request URL contains the API endpoint along with the target language.</p>
<p>Inside the <code>TranslateText</code> method, we will create a new <code>HttpRequestMessage</code>. This HTTP request is a Post request. We will pass the subscription key in the header of the request. The Translator Text API returns a JSON object, which will be deserialized to an array of type <code>TranslationResult</code>. The output contains the translated text as well as the language detected for the input text.</p>
<p>The <code>GetAvailableLanguages</code> method will return the list of all the language supported by the Translate Text API. We will set the request URI and create a <code>HttpRequestMessage</code> which will be a Get request. This request URL will return a JSON object which will be deserialized to an object of type <code>AvailableLanguage</code>.</p>
<h2 id="heading-configuring-the-service">Configuring the Service</h2>
<p>To make the service available to the components we need to configure it on the server-side app. Open the <code>Startup.cs</code> file. Add the following line inside the <code>[ConfigureServices](https://github.com/AnkitSharma-007/Blazor-Translator-Azure-Cognitive-Services/blob/master/BlazorTranslator/Startup.cs#L28)</code> method of Startup class.</p>
<pre><code>services.AddSingleton&lt;TranslationService&gt;();
</code></pre><h2 id="heading-creating-the-blazor-ui-component">Creating the Blazor UI Component</h2>
<p>We will add the Razor page in <code>BlazorTranslator/Pages</code> folder. By default, we have “Counter” and “Fetch Data” pages provided in our application. These default pages will not affect our application but for the sake of this tutorial, we will delete fetchdata and counter pages from <code>BlazorTranslator/Pages</code> folder.</p>
<p>Right-click on <code>BlazorTranslator/Pages</code> folder and then select Add &gt;&gt; New Item. An “Add New Item” dialog box will open, select “Visual C#” from the left panel, then select “Razor Component” from the templates panel, put the name as <code>Translator.razor</code>. Click <code>Add</code>. Refer to the image shown below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/AddRazorComp-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Open the <code>[Translator.razor](https://github.com/AnkitSharma-007/Blazor-Translator-Azure-Cognitive-Services/blob/master/BlazorTranslator/Pages/Translator.razor)</code> file and add the following code at the top.</p>
<pre><code>@page <span class="hljs-string">"/translator"</span>
@using BlazorTranslator.Models
@using BlazorTranslator.Data
@inject TranslationService translationService
</code></pre><p>We have defined the route for this component. We are also injecting the <code>TranslationService</code> in this component.</p>
<p>Now we will add the following HTML code in this file.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>Multilanguage translator using Microsoft Translator API Cognitive Service<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">hr</span> /&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"row"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-6"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span> @<span class="hljs-attr">bind</span>=<span class="hljs-string">"inputLanguage"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">""</span>&gt;</span>-- Select input language --<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
                @foreach (KeyValuePair<span class="hljs-tag">&lt;<span class="hljs-name">string,</span> <span class="hljs-attr">LanguageDetails</span>&gt;</span> lang in LanguageList)
                {
                    <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"@lang.Key"</span>&gt;</span>@lang.Value.Name<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
                }
            <span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span> <span class="hljs-attr">placeholder</span>=<span class="hljs-string">"Enter text to translate"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control translation-box"</span> <span class="hljs-attr">rows</span>=<span class="hljs-string">"5"</span> @<span class="hljs-attr">bind</span>=<span class="hljs-string">"@inputText"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">textarea</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"col-md-6"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">select</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span> @<span class="hljs-attr">onchange</span>=<span class="hljs-string">"SelectLanguage"</span>&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">""</span>&gt;</span>-- Select target language --<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
                @foreach (KeyValuePair<span class="hljs-tag">&lt;<span class="hljs-name">string,</span> <span class="hljs-attr">LanguageDetails</span>&gt;</span> lang in LanguageList)
                {
                    <span class="hljs-tag">&lt;<span class="hljs-name">option</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"@lang.Key"</span>&gt;</span>@lang.Value.Name<span class="hljs-tag">&lt;/<span class="hljs-name">option</span>&gt;</span>
                }
            <span class="hljs-tag">&lt;/<span class="hljs-name">select</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">textarea</span> <span class="hljs-attr">disabled</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control translation-box"</span> <span class="hljs-attr">rows</span>=<span class="hljs-string">"5"</span>&gt;</span>@outputText<span class="hljs-tag">&lt;/<span class="hljs-name">textarea</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"text-center"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"btn btn-primary btn-lg"</span> @<span class="hljs-attr">onclick</span>=<span class="hljs-string">"Translate"</span>&gt;</span>Translate<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>We have defined two dropdown lists, one each for input language and the target language. The Azure Translate Text API will detect the input language and we will use that value to populate the dropdown for input language. We have also defined two text areas for the input and the translated text.</p>
<p>Finally, add the following code in the <code>@code</code> section of the page.</p>
<pre><code class="lang-c#">@code {
    <span class="hljs-keyword">private</span> TranslationResult[] translations;
    <span class="hljs-keyword">private</span> AvailableLanguage availableLanguages;

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> outputLanguage { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> inputLanguage { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }

    <span class="hljs-keyword">string</span> inputText { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">string</span> outputText { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Dictionary</span>&lt;<span class="hljs-title">string</span>, <span class="hljs-title">LanguageDetails</span>&gt; LanguageList</span> = <span class="hljs-keyword">new</span> Dictionary&lt;<span class="hljs-keyword">string</span>, LanguageDetails&gt;();

    <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">override</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">OnInitializedAsync</span>(<span class="hljs-params"></span>)</span>
    {
        availableLanguages = <span class="hljs-keyword">await</span> translationService.GetAvailableLanguages();
        LanguageList = availableLanguages.Translation;
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">SelectLanguage</span>(<span class="hljs-params">ChangeEventArgs langEvent</span>)</span>
    {
        <span class="hljs-keyword">this</span>.outputLanguage = langEvent.Value.ToString();
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">Translate</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">string</span>.IsNullOrEmpty(outputLanguage))
        {
            translations = <span class="hljs-keyword">await</span> translationService.GetTranslatation(<span class="hljs-keyword">this</span>.inputText, <span class="hljs-keyword">this</span>.outputLanguage);
            outputText = translations[<span class="hljs-number">0</span>].Translations[<span class="hljs-number">0</span>].Text;
            inputLanguage = translations[<span class="hljs-number">0</span>].DetectedLanguage.Language;
        }
    }
}
</code></pre>
<p>We are invoking the <code>GetAvailableLanguages</code> method from our service inside the <code>OnInitializedAsync</code>. This <code>OnInitializedAsync</code> is a lifecycle method that will be invoked upon component initialization. This will make sure that the language dropdown will be populated as the page loads.</p>
<p>The <code>SelectLanguage</code> method will set the <code>outputLanguage</code> for the translation. The Translate method will invoke the <code>GetTranslatation</code> method from the service. We will set the <code>outputText</code> and the language detected for the <code>inputLanguage</code> as returned from the service.</p>
<h2 id="heading-add-styling-for-the-translator-component">Add styling for the Translator component</h2>
<p>Navigate to <code>[BlazorTranslator\wwwroot\css\site.css](https://github.com/AnkitSharma-007/Blazor-Translator-Azure-Cognitive-Services/blob/master/BlazorTranslator/wwwroot/css/site.css#L185-L187)</code> file and put the following style definition inside it.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.translation-box</span> {
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">15px</span> <span class="hljs-number">0px</span>;
}
</code></pre>
<h2 id="heading-adding-link-to-navigation-menu">Adding Link to Navigation menu</h2>
<p>The last step is to add the link of our Translator component in the navigation menu. Open <code>[BlazorTranslator/Shared/NavMenu.razor](https://github.com/AnkitSharma-007/Blazor-Translator-Azure-Cognitive-Services/blob/master/BlazorTranslator/Shared/NavMenu.razor#L15-L19)</code> file and add the following code into it.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nav-item px-3"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">NavLink</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"nav-link"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"translator"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"oi oi-list-rich"</span> <span class="hljs-attr">aria-hidden</span>=<span class="hljs-string">"true"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span> Translator
    <span class="hljs-tag">&lt;/<span class="hljs-name">NavLink</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
</code></pre>
<p>Remove the navigation links for Counter and Fetch-data components as they are not required for this application.</p>
<h2 id="heading-execution-demo">Execution Demo</h2>
<p>Press F5 to launch the application. Click on the Translator button on the nav menu in the left. You can perform the multilanguage translation as shown in the image below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/03/BlazorTranslator-1.gif" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-summary">Summary</h2>
<p>We have created a Translator Text Cognitive Services resource on Azure. We have used the Translator Text API to create a multilanguage translator using Blazor. This translator supports more than 60 languages for translation. We fetched the list of supported languages for translation from the global API endpoint for Translator Text.</p>
<p>Get the Source code from <a target="_blank" href="https://github.com/AnkitSharma-007/Blazor-Translator-Azure-Cognitive-Services">GitHub</a> and play around to get a better understanding.</p>
<h2 id="heading-see-also">See Also</h2>
<ul>
<li><a target="_blank" href="https://ankitsharmablogs.com/optical-character-reader-using-blazor-and-computer-vision/">Optical Character Reader Using Blazor And Computer Vision</a></li>
<li><a target="_blank" href="https://ankitsharmablogs.com/facebook-authentication-and-authorization-in-server-side-blazor-app/">Facebook Authentication And Authorization In Server-Side Blazor App</a></li>
<li><a target="_blank" href="https://ankitsharmablogs.com/google-authentication-and-authorization-in-server-side-blazor-app/">Google Authentication And Authorization In Server-Side Blazor App</a></li>
<li><a target="_blank" href="https://ankitsharmablogs.com/blazor-crud-using-google-cloud-firestore/">Blazor CRUD Using Google Cloud Firestore</a></li>
<li><a target="_blank" href="https://ankitsharmablogs.com/hosting-a-blazor-application-on-firebase/">Hosting A Blazor Application on Firebase</a></li>
<li><a target="_blank" href="https://ankitsharmablogs.com/localization-in-angular-using-i18n-tools/">Localization In Angular Using i18n Tools</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to choose a library for translating your JavaScript apps ]]>
                </title>
                <description>
                    <![CDATA[ By Anastasia In the previous articles, we have seen how to perform localization on the back-end. Specifically, we’ve covered Rails and Phoenix frameworks. Today, however, we are going to talk about libraries for translating JavaScript apps and briefl... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-choose-a-library-for-translating-your-javascript-apps-10f68de6a1d1/</link>
                <guid isPermaLink="false">66c3507f5ced6d98e4bd333e</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ startup ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ translation ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 31 Jan 2019 08:25:22 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*IklbYvLxPek-M3vr2wTmoA.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Anastasia</p>
<p>In the previous articles, we have seen how to perform localization on the back-end. Specifically, we’ve covered <a target="_blank" href="https://blog.lokalise.co/rails-i18n/">Rails</a> and <a target="_blank" href="https://blog.lokalise.co/localization-of-phoenix-applications/">Phoenix</a> frameworks. Today, however, we are going to talk about libraries for translating JavaScript apps and briefly see them in action.</p>
<p>It appears that there are quite a lot of available solutions, so you may ask: “Which one should I use?”. The most obvious (and perhaps the sanest) answer would be: “It depends”. Ideally, you should check each library and then decide which one you prefer.</p>
<p>Therefore, in this article I will give you a general introduction to the following solutions:</p>
<ul>
<li>Globalize</li>
<li>I18next</li>
<li>jQuery.I18n</li>
<li>Polyglot.js</li>
</ul>
<p>Note that we will be talking about localizing vanilla JS apps, not about some specific client-side framework. Also, we won’t dive deep into each library because the article would become much, much longer. I’ll only give you a gentle introduction to each tool. Then we’ll try to compare them and come to some general conclusion.</p>
<p>Shall we start?</p>
<h3 id="heading-globalize">Globalize</h3>
<p><a target="_blank" href="https://github.com/globalizejs/globalize">Globalize</a> is a complex translation and localization JS library initially introduced by jQuery team. This library utilizes <a target="_blank" href="http://cldr.unicode.org/">Unicode common locale data repository</a> (CLDR) and has lots of features including:</p>
<ul>
<li>Message formatting</li>
<li>Date/time parsing and the ability to work with relative time</li>
<li>Pluralization support</li>
<li>Numbers parsing and currency formatting</li>
<li>Ability to work with units (days, minutes, seconds, miles per hour etc)</li>
</ul>
<p>Globalize works consistently in browser and NodeJS, has a modular code and allows to require as little modules as needed. While relying on CLDR data, it does not host or hardcode it directly. Developers may choose which data to load. This also means that you can update CLDR data yourself, without waiting for a new version of Globalize to be released. You may read a bit more about Globalize’s features here.</p>
<p>Now let’s see this library in action. There is a <a target="_blank" href="https://github.com/globalizejs/globalize#getting-started">Getting started guide</a> that explains how to install all the required modules on your machine using a package manager. However, we’ll choose a more complex way of loading everything manually.</p>
<h4 id="heading-getting-cldr-data">Getting CLDR Data</h4>
<p>CLDR is really huge and so there is no reason to download all its content. Luckily, Globalize documentation <a target="_blank" href="https://github.com/globalizejs/globalize#2-cldr-content">summarizes what you have to load</a> when using specific modules. Also, there is an <a target="_blank" href="https://johnnyreilly.github.io/globalize-so-what-cha-want/#/?currency=true&amp;date=true&amp;message=true&amp;number=true&amp;plural=true&amp;relativeTime=true&amp;unit=true">online tool</a> where you just pick the modules that will be used and then see what JSON files you need to load. In this demo, I’ll only use “core”, “message”, and “plural” modules, therefore, we require the following files:</p>
<p>To learn more about how CLDR is organized, <a target="_blank" href="https://github.com/unicode-cldr/cldr-json#package-organization">refer to this doc</a>. It may seem complex at first but in reality, things are quite simple: you just cherry-pick the required files, download them and use in your project.</p>
<p>I’ve placed the files mentioned above to the <code>cldr/supplemental</code> folder of my project but you may organize them differently of course.</p>
<p>The next question is: how do we actually load this data? Well, <a target="_blank" href="https://github.com/globalizejs/globalize/blob/master/doc/cldr.md#how-do-i-load-cldr-data-into-globalize">there are two alternatives</a>: by embedding it inside the <code>Globalize.load</code> function or by using an <a target="_blank" href="https://api.jquery.com/jQuery.get/">asynchronous <code>$.get()</code> method</a>. The second option is much more robust, so let’s create a new JS file with the following content:</p>
<pre><code><span class="hljs-comment">// i18n.js $.when( $.get("cldr/supplemental/likelySubtags.json"), $.get("cldr/supplemental/ordinals.json"), $.get("cldr/supplemental/plurals.json"), ).then(function() { // Normalize $.get results, we only need the JSON, not the request statuses. return [].slice.apply(arguments, [0]).map(function(result) { return result[0]; }); }).then(Globalize.load).then(function() { // your Globalize code here });</span>
</code></pre><p>In this example, we’re loading JSON data and feed it to Globalize. We’re using promises, so the custom code should be placed into the second <code>then</code> and will be executed as soon as everything is loaded successfully. Feel free to refactor this code without using jQuery.</p>
<h4 id="heading-loading-other-files">Loading Other Files</h4>
<p>After loading CLDR JSON files, you require a <a target="_blank" href="https://github.com/globalizejs/globalize#1-dependencies">bunch of other scripts</a>:</p>
<ul>
<li>jQuery (note by the way that Globalize itself is not jQuery-based)</li>
<li><a target="_blank" href="https://github.com/rxaviers/cldrjs">CLDR JS</a></li>
<li>Globalize JS core module</li>
<li>Any other modules that you wish to use in your app</li>
</ul>
<p>jQuery and Cldr.js are external dependencies and you may load them from a CDN (for example, from <a target="_blank" href="https://cdnjs.com/">cdnjs.com</a>).</p>
<p>Then download Globalize from the Releases section. Open the <code>dist</code> folder. Pick all the files that you require and place them under the <code>globalize</code> directory.</p>
<p>After that load all the scripts in the proper order:</p>
<pre><code>&lt;!-- index.html --&gt; &lt;!DOCTYPE html&gt; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdnjs.cloudflare.com/ajax/libs/cldrjs/0.5.1/cldr.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdnjs.cloudflare.com/ajax/libs/cldrjs/0.5.1/cldr/event.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdnjs.cloudflare.com/ajax/libs/cldrjs/0.5.1/cldr/supplemental.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"globalize/globalize.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"globalize/plural.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"globalize/message.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"i18n.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre><p>All in all, this is it. Now you may refer to the <a target="_blank" href="https://github.com/globalizejs/globalize#api">API section</a> of the Globalize docs and see what functions you may utilize.</p>
<h4 id="heading-using-it">Using It</h4>
<p>You can provide translation messages with the help of <code>[loadMessages](https://github.com/globalizejs/globalize/blob/master/doc/api/message/load-messages.md)</code> <a target="_blank" href="https://github.com/globalizejs/globalize/blob/master/doc/api/message/load-messages.md">function</a>:</p>
<pre><code>$.when( <span class="hljs-comment">// ... }).then(Globalize.load).then(function() { Globalize.loadMessages({ "en": { 'welcome': 'Welcome, {name}!' } }); });</span>
</code></pre><p>Then instantiate Globalize with the desired locale and perform the actual translations:</p>
<pre><code><span class="hljs-comment">// loadMessages... var globalize = new Globalize("en"); console.log(globalize.messageFormatter('welcome')({name: 'Username'}));</span>
</code></pre><p><code>[messageFormatter](https://github.com/globalizejs/globalize/blob/master/doc/api/message/message-formatter.md)</code> returns a formatted translation. As you can see from this example, it supports interpolation, but there is more. Want to introduce pluralization? Simple!</p>
<p>Add a new message:</p>
<pre><code>Globalize.loadMessages({ <span class="hljs-string">"en"</span>: { <span class="hljs-string">'welcome'</span>: <span class="hljs-string">'Welcome, {name}!'</span>, <span class="hljs-string">'messages'</span>: [ <span class="hljs-string">"You have {count, plural,"</span>, <span class="hljs-string">" one {one message}"</span>, <span class="hljs-string">" other {{count} messages}"</span>, <span class="hljs-string">"}"</span> ] } });
</code></pre><p>Note that the message may span multiple lines but in this case, it should be defined as an array. Here we are utilizing pluralization and providing two forms: singular and plural. <code>count</code> is an interpolation.</p>
<p>Now display this message:</p>
<pre><code>taskFormatter = globalize.messageFormatter(<span class="hljs-string">"messages"</span>); <span class="hljs-built_in">console</span>.log(taskFormatter({ <span class="hljs-attr">count</span>: <span class="hljs-number">10</span> }));
</code></pre><p>You may utilize other modules in pretty much the same way.</p>
<p>To summarize, Globalize is a great powerful solution with good documentation and nice support. It may require some time to set it up but working with it is convenient and intuitive.</p>
<h3 id="heading-i18next">I18next</h3>
<p>I18next is a JavaScript localization framework providing all the necessary tools to translate your applications. It has loads of various features including:</p>
<ul>
<li><a target="_blank" href="https://www.i18next.com/overview/supported-frameworks">Support for front-end frameworks</a> including React, Angular, Vue etc</li>
<li>Supports for various formats (including Polyglot which we’ll discuss later)</li>
<li>Message formatting</li>
<li>Pluralization</li>
<li>Fallbacks</li>
<li>Ability to load translation data from various resources</li>
<li>…and many, many other <a target="_blank" href="https://www.i18next.com/overview/plugins-and-utils">utilities and plugins</a></li>
</ul>
<h4 id="heading-loading-required-files">Loading Required Files</h4>
<p>To get started with I18next you may simply require it from CDN, for example:</p>
<pre><code>&lt;!DOCTYPE html&gt; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdnjs.cloudflare.com/ajax/libs/i18next/14.0.1/i18next.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre><p>Of course, it can be also installed with NPM or Yarn as explained <a target="_blank" href="https://www.i18next.com/overview/getting-started">here</a>.</p>
<h4 id="heading-configuration">Configuration</h4>
<p>As I already mentioned above, I18next allows you to load translations from the backend. You may also provide them in the following way:</p>
<pre><code>i18next.init({ <span class="hljs-attr">lng</span>: <span class="hljs-string">'en'</span>, <span class="hljs-attr">resources</span>: { <span class="hljs-attr">en</span>: { <span class="hljs-attr">translation</span>: { <span class="hljs-string">"hi"</span>: <span class="hljs-string">"Welcome"</span> } } } }).then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">t</span>) </span>{ <span class="hljs-comment">// ready to go! });</span>
</code></pre><p>Note that I am also setting English as a default locale.</p>
<p>There are many other configuration options that are listed on the <a target="_blank" href="https://www.i18next.com/overview/configuration-options">corresponding page</a>.</p>
<h4 id="heading-using-it-1">Using It</h4>
<p>You may perform translations in the following way:</p>
<pre><code><span class="hljs-comment">// ... init .then(function(t) { // initialized and ready to go! console.log(i18next.t('hi')); });</span>
</code></pre><p><code>[t](https://www.i18next.com/overview/api#t)</code> <a target="_blank" href="https://www.i18next.com/overview/api#t">is a function</a> to look up translation based on the provided key. It can also work with interpolation, for instance:</p>
<pre><code>i18next.t(<span class="hljs-string">'hi'</span>, {<span class="hljs-attr">name</span>: <span class="hljs-string">'Username'</span>});
</code></pre><p><a target="_blank" href="https://www.i18next.com/translation-function/plurals">Pluralization</a> is supported too. To start using it, define singular and plural forms in the following way:</p>
<pre><code>{ <span class="hljs-string">"msg"</span>: <span class="hljs-string">"one message"</span>, <span class="hljs-string">"msg_plural"</span>: <span class="hljs-string">"{{count}} messages"</span> }
</code></pre><p>Note the <code>_plural</code> part that has to be provided for plural forms. Some languages require <a target="_blank" href="https://www.i18next.com/translation-function/plurals#languages-with-multiple-plurals">multiple forms</a>. In this case use <code>_0</code>, <code>_1</code>, and other post-fixes, for example:</p>
<pre><code>{ <span class="hljs-string">"key_0"</span>: <span class="hljs-string">"zero"</span>, <span class="hljs-string">"key_1"</span>: <span class="hljs-string">"singular"</span>, <span class="hljs-string">"key_2"</span>: <span class="hljs-string">"two"</span>, <span class="hljs-string">"key_3"</span>: <span class="hljs-string">"few"</span>, <span class="hljs-string">"key_4"</span>: <span class="hljs-string">"many"</span>, <span class="hljs-string">"key_5"</span>: <span class="hljs-string">"other"</span> }
</code></pre><p>Then just use the <code>t</code> function again:</p>
<pre><code>i18next.t(<span class="hljs-string">'msg'</span>, {<span class="hljs-attr">count</span>: <span class="hljs-number">10</span>});
</code></pre><p>I18next allows you to provide <a target="_blank" href="https://www.i18next.com/translation-function/context">context for the translation</a>. This is particularly important when working with gender information:</p>
<pre><code>{ <span class="hljs-string">"friend"</span>: <span class="hljs-string">"A friend"</span>, <span class="hljs-string">"friend_male"</span>: <span class="hljs-string">"A boyfriend"</span>, <span class="hljs-string">"friend_female"</span>: <span class="hljs-string">"A girlfriend"</span> }
</code></pre><p><code>_male</code> and <code>_female</code> here are contexts that you can set in the following way:</p>
<pre><code>i18next.t(<span class="hljs-string">'friend'</span>); <span class="hljs-comment">// ==&gt; No context here, so return "A friend" i18next.t('friend', { context: 'male' }); // -&gt; A context is present, so return "A boyfriend"</span>
</code></pre><p>Don’t hesitate to browse other examples in the I18next’s docs on how to <a target="_blank" href="https://www.i18next.com/translation-function/nesting">enable nesting in translations</a>, <a target="_blank" href="https://www.i18next.com/translation-function/objects-and-arrays">work with objects</a>, or <a target="_blank" href="https://www.i18next.com/principles/fallback">setup fallbacks</a>.</p>
<p>To summarize, I18next is a great framework with an array of various plugins and utilities. This framework is quite large and heavy, but you receive all the necessary localization tools that can be extended as necessary. Moreover, setting this framework up is simple and requires very little time. So, I would say this is a great candidate for complex applications!</p>
<h3 id="heading-jqueryi18n">jQuery.I18n</h3>
<p><a target="_blank" href="https://github.com/wikimedia/jquery.i18n">jQuery.I18n</a> is yet another popular solution presented to you by <a target="_blank" href="https://www.mediawiki.org/wiki/Wikimedia_Language_engineering">Wikimedia Engineering team</a> allowing to translate your JavaScript applications. Wikimedia, in turn, is a company behind <a target="_blank" href="http://en.wikipedia.org/">Wikipedia project</a>, one of the most popular websites in the world. jQuery.I18n is used in Wikipedia internally, so you can be sure this library won’t be abandoned out of the blue. It utilizes a JSON-based localization format and supports the following <a target="_blank" href="https://github.com/wikimedia/jquery.i18n#features">features</a>:</p>
<ul>
<li>Ability to meta information and document your messages</li>
<li>Supports pluralization with the help of CLDR</li>
<li>Gender information</li>
<li>Support for grammar forms</li>
<li>Fallback chains</li>
<li>Ability to customize message parser</li>
<li>Has modular code</li>
</ul>
<p>Let’s see jQuery.I18n in action now.</p>
<h4 id="heading-loading-required-files-1">Loading Required Files</h4>
<p>First of all, download the library itself and initialize its dependencies:</p>
<pre><code>$ git clone https:<span class="hljs-comment">//github.com/wikimedia/jquery.i18n.git $ cd jquery.i18n $ git submodule update --init</span>
</code></pre><p><code>jquery.i18n/src</code> folder contains the library’s files. Pick the modules that you need (at the very least, you’ll require the core <code>jquery.i18n.js</code>) and place them to your application. The idea here is similar to the one in Globalize. The <code>languages</code> folder contains some helpers for various locales. If you are supporting one of these, don’t forget to copy the corresponding file as well.</p>
<p>If your application works with plural forms, then the <code>CLDRPluralRuleParser.js</code> file is necessary too (it can be found under the <code>jquery.i18n\libs\CLDRPluralRuleParser\src</code> path).</p>
<p>After you are ready, load the files in the proper order, for example:</p>
<pre><code>&lt;!DOCTYPE html&gt; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"lib/CLDRPluralRuleParser.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"lib/jquery.i18n.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"lib/jquery.i18n.messagestore.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"lib/jquery.i18n.fallbacks.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"lib/jquery.i18n.language.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"lib/jquery.i18n.parser.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"lib/jquery.i18n.emitter.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"lib/jquery.i18n.emitter.bidi.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre><h4 id="heading-providing-translations">Providing Translations</h4>
<p>As mentioned above, <a target="_blank" href="https://github.com/wikimedia/jquery.i18n#message-file-format">translations for the jQuery.I18n library</a> are stored inside JSON files. You may separate translation data for different languages, or store everything in a single file. Create a <code>i18n/i18n.json</code> file with the following contents:</p>
<pre><code>{ <span class="hljs-string">"@metadata"</span>: { <span class="hljs-string">"authors"</span>: [ <span class="hljs-string">"Ilya"</span> ], <span class="hljs-string">"last-updated"</span>: <span class="hljs-string">"2019-01-29"</span>, <span class="hljs-string">"message-documentation"</span>: <span class="hljs-string">"qqq"</span> }, <span class="hljs-string">"welcome"</span>: <span class="hljs-string">"Hi!"</span> }
</code></pre><p><a target="_blank" href="https://github.com/wikimedia/jquery.i18n#message-loading">To load this file</a>, use the following code (note that I am also providing a default locale):</p>
<pre><code><span class="hljs-comment">// main.js jQuery(document).ready(function() { $.i18n({locale: 'en'}).load({ en: 'i18n/i18n.json' }).done(function() { // success }) });</span>
</code></pre><p>Include this script on your main page and you are good to go!</p>
<h4 id="heading-using-it-2">Using It</h4>
<p>For instance, you may output a welcoming message in the following way:</p>
<pre><code><span class="hljs-built_in">console</span>.log($.i18n(<span class="hljs-string">'welcome'</span>, <span class="hljs-string">'Username'</span>));
</code></pre><p><a target="_blank" href="https://github.com/wikimedia/jquery.i18n#plurals">Pluralization</a> is performed in the following way:</p>
<pre><code>{ <span class="hljs-string">"msg"</span>: <span class="hljs-string">"You have $1 {{PLURAL:$1|message|messages}}"</span> }
</code></pre><p>So, you have one key that lists all the available forms, both plural, and singular. <code>$1</code> is a <a target="_blank" href="https://github.com/wikimedia/jquery.i18n#placeholders">placeholder</a> for the interpolation. You may have as many placeholders as needed, and they should be named in a sequential manner: <code>$2</code>, <code>$3</code> etc.</p>
<p>Then just utilize this new key:</p>
<pre><code>$.i18n(<span class="hljs-string">'msg'</span>, <span class="hljs-number">10</span>); <span class="hljs-comment">// $1 placeholder will have a value of 10</span>
</code></pre><p>The context of the translation is defined in pretty much the same way. For example, you can work with <a target="_blank" href="https://github.com/wikimedia/jquery.i18n#gender">gender information</a>:</p>
<pre><code><span class="hljs-string">"friend"</span>: <span class="hljs-string">"Some text... {{GENDER:$1|A boyfriend|A girlfriend}}"</span>
</code></pre><p>Provide the context:</p>
<pre><code>$.i18n(<span class="hljs-string">'friend'</span>, <span class="hljs-string">'female'</span>);
</code></pre><p>One interesting feature is the support for the <code>[data-*](https://github.com/wikimedia/jquery.i18n#data-api)</code> <a target="_blank" href="https://github.com/wikimedia/jquery.i18n#data-api">HTML5 attributes</a>. You just need to add a <code>data-i18n</code> attribute to your tags, provide the key as the value, and then apply <code>.i18n()</code> function directly to those elements or their parent. For example:</p>
<pre><code>&lt;body&gt; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">data-i18n</span>=<span class="hljs-string">"translation-key"</span>&gt;</span>Fallback text goes here<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">data-i18n</span>=<span class="hljs-string">"another-key"</span>&gt;</span>Fallback text goes here<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span> &lt;/body&gt;
</code></pre><p>Now inside your code simply say:</p>
<pre><code>$(<span class="hljs-string">'body'</span>).i18n();
</code></pre><p>The script is going to traverse all elements inside <code>body</code> and replace their contents with the messages under the provided translation keys. If the key cannot be found, the initial content will be displayed as a fallback.</p>
<p>jQuery.I18n is a powerful and quite easy-to-use library. Basically, you may call it a direct competitor to Globalize as these two solutions have similar functionality. To some people, Globalize may seem more favorable as it doesn’t rely on jQuery. On the other hand, many websites do requite jQuery, so that’s perhaps not a deal-breaker. If you’d like to mostly stay away from CLDR then jQuery.I18n is, of course, a better option. This library also allows to store metadata inside your translation files, supports <code>[data-*](https://github.com/wikimedia/jquery.i18n#data-api)</code> <a target="_blank" href="https://github.com/wikimedia/jquery.i18n#data-api">attributes API</a>, supports so-called <a target="_blank" href="https://github.com/wikimedia/jquery.i18n#magic-word-support">“magic words”</a>, and more. So, as you see, there is really a lot of features!</p>
<h3 id="heading-polyglot">Polyglot</h3>
<p>The last solution we’ll talk about is <a target="_blank" href="https://github.com/airbnb/polyglot.js">Polyglot.js</a> created by Airbnb. As long as Airbnb service is worldwide, it’s essential for them to have proper localization. Polyglot, in contrast to the previously discussed libraries, is a very small solution really. It has only the following features:</p>
<ul>
<li>Basic translation features</li>
<li>Interpolation</li>
<li>Pluralization</li>
</ul>
<p>It may become an excellent candidate for smaller and less intricate apps that do not require all the complexities of, say, Globalize. Now let’s see how to get started with Polyglot!</p>
<h4 id="heading-loading-files">Loading Files</h4>
<p>Polyglot has no external dependencies at all, so all you need to do is hook up the main file:</p>
<pre><code>&lt;!DOCTYPE html&gt; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"https://cdnjs.cloudflare.com/ajax/libs/polyglot.js/2.2.2/polyglot.min.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre><h4 id="heading-providing-translations-and-using-it">Providing Translations and Using It</h4>
<p>Now we can provide translations (aka “phrases”) and set the default locale:</p>
<pre><code><span class="hljs-keyword">var</span> polyglot = <span class="hljs-keyword">new</span> Polyglot({ <span class="hljs-attr">locale</span>: <span class="hljs-string">'en'</span>, <span class="hljs-attr">phrases</span>: { <span class="hljs-string">"message_count"</span>: <span class="hljs-string">"%{smart_count} message |||| %{smart_count} messages"</span> } });
</code></pre><p>In this example the default locale is English. Also, there is a <code>message_count</code> key that provides singular and plural forms separated with 4 pipelines (for other languages there may be more forms). Oddly enough, <a target="_blank" href="https://github.com/airbnb/polyglot.js#pluralization">pluralization relies on the <code>smart_count</code> interpolated value</a>, so you must provide it in the following way:</p>
<pre><code><span class="hljs-built_in">console</span>.log(polyglot.t(<span class="hljs-string">'message_count'</span>, {<span class="hljs-attr">smart_count</span>: <span class="hljs-number">2</span>}));
</code></pre><p>This is it! There is not much else to say about the translation process, as it relies only on the <code>t</code> function. You may find some more examples of using Polyglot in the <a target="_blank" href="https://github.com/airbnb/polyglot.js#translation">official doc</a>.</p>
<h3 id="heading-summing-everything-up">Summing Everything Up</h3>
<p>Potentially, there is a lot of different features to compare (some may be more or less relevant for your setup), but here is a brief summary of the discussed solutions:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/hj2GuNOKjpR8g-pZMcqoHPf9FegIwkGZDXEK" alt="Image" width="700" height="750" loading="lazy"></p>
<p>A couple of things to note:</p>
<ul>
<li>I18next <a target="_blank" href="https://github.com/i18next/i18next-gitbook/blob/master/translation-function/formatting.md">does support various formatting</a> but it requires external dependencies like <a target="_blank" href="https://momentjs.com/">moment.js</a></li>
<li>jQuery.I18n requires CLDR Parser only for pluralization</li>
<li>I18next provides lots of plugins to connect with the client-side framework, but other solutions can play nicely with frameworks as well (you may just need to spend more time to integrate everything)</li>
<li>You may work with gender information (and, more broadly speaking, with contexts) in any library — it just may be less convenient and present more complexities</li>
</ul>
<p>From my experience, I18next is a very powerful and feature-rich tool that you can easily get started with. At the same time, Globalize’s modular approach and relation on CLDR might be convenient, especially for larger and more complex applications. I have not used jQuery.I18n that much but as long as the Wikimedia team utilizes it, one can conclude that this is also a feasible tool with vast functionality. And, Polyglot is a nice tiny helper for simpler apps that also plays very nicely with server-side frameworks like Rails.</p>
<h3 id="heading-make-your-life-easier-with-lokalise">Make Your Life Easier With Lokalise</h3>
<p>Supporting multiple languages on a big website may become a serious pain. You must make sure that all the keys are translated for each and every locale. Luckily, there is a solution to this problem: the Lokalise platform that <a target="_blank" href="https://lokalise.co/features">makes working with the localization files much simpler</a>. Let me guide you through the initial setup which is nothing complex really.</p>
<ul>
<li>To get started, <a target="_blank" href="https://lokalise.co/signup">grab your free trial</a></li>
<li>Create a new project, give it some name, and set English as a base language</li>
<li>Click “Upload Language Files”</li>
<li>Upload translation files for all your languages</li>
<li>Proceed to the project, and edit your translations as needed</li>
<li>You may also contact a professional translator to do the job for you</li>
<li>Next simply download your files back</li>
<li>Profit!</li>
</ul>
<p>Lokalise has many more features including support for dozens of platforms and formats, and even the possibility to upload screenshots to read texts from them. So, stick with Lokalise and make your life easier!</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>In this article, we were talking about the available tools used to translate JavaScript applications. We’ve covered Globalize, I18next and jQuery.I18n (larger and more complex solutions), as well as Polyglot which appeared to be a much simpler and smaller library. We’ve compared these libraries and came up with some conclusions about them. Hopefully, now you will be able to pick an I18n solution that entirely suits you. Don’t be afraid to research, experiment, and ultimately choose the tool that works for you! After all, it will be more complicated to switch to another localization library when your application is half-finished.</p>
<p>I thank you for staying with me, and until the next time!</p>
<p><em>Originally published at <a target="_blank" href="https://blog.lokalise.co/comparing-libraries-translating-js-apps/">blog.lokalise.co</a> on January 31, 2019.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to store translations inside a database with Globalize ]]>
                </title>
                <description>
                    <![CDATA[ By Anastasia In one of my previous articles, I talked about the process of internationalizing Rails applications. That article explained all I18n basics, but it was revolving around placing all translations inside YAML files. There is nothing wrong w... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-store-translations-inside-a-database-with-globalize-63cd033e29e6/</link>
                <guid isPermaLink="false">66c354eadae03919d93dc01a</guid>
                
                    <category>
                        <![CDATA[ Apps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Rails ]]>
                    </category>
                
                    <category>
                        <![CDATA[ startup ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ translation ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 16 Nov 2018 10:01:23 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*m8n4yc-F8Ln4EcnbL3H-CQ.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Anastasia</p>
<p>In one of my previous articles, I talked about the process of <a target="_blank" href="https://blog.lokalise.co/rails-i18n/">internationalizing Rails applications</a>. That article explained all <a target="_blank" href="https://guides.rubyonrails.org/i18n.html">I18n</a> basics, but it was revolving around placing all translations inside YAML files. There is nothing wrong with this approach, but unfortunately it does not always work.</p>
<p>Suppose your website has lots of user-generated content which should be adapted for different languages. I propose that you <em>store your translations inside the database.</em> Why will YAML files not work in this case?</p>
<ul>
<li>The content itself may be quite large and it would be inconvenient to store it inside a file</li>
<li>The content is dynamic and users should be able to create translated versions themselves, without the help of the site’s developer</li>
</ul>
<p>It appears that the I18n module <a target="_blank" href="https://guides.rubyonrails.org/i18n.html#using-different-backends">allows you to define a custom backend</a> that, for instance, may be powered by ActiveRecord. Luckily, there is no need to craft your own solution as there is already an existing one: <a target="_blank" href="https://github.com/globalize/globalize">Globalize</a>. Globalize is a battle-tested library characterized as “Rails I18n de-facto standard library for ActiveRecord model/data translation.” With its help you can easily translate model attributes, scope them, introduce fallbacks, and so on.</p>
<p>So, in this article we are going to talk about Globalize and see it in action by creating a sample Rails application. Shall we start?</p>
<h3 id="heading-preparing-the-application">Preparing the Application</h3>
<p>Let’s get started by generating a new Rails app:</p>
<pre><code>rails <span class="hljs-keyword">new</span> GlobalizeSample
</code></pre><p>I’ll assume you are using <em>Rails 5.2.1</em> for this demo but still the described concepts apply to earlier versions as well.</p>
<p>Let’s suppose we are building an <a target="_blank" href="https://www.shopify.com/plus">international online shop</a> showcasing various products. These products will be added by the administrator, and so we can’t know what the content will be ahead of the game. This means that the traditional method of using YAML files to store translations won’t work. Our content manager will have access to the CMS only, and we would rather not give them access to the source code of the app (I shudder to think about it!).</p>
<p>But, fear not, in the next section we will overcome this problem easily. For now, however, let’s take care of the basics.</p>
<h3 id="heading-administering-products">Administering Products</h3>
<p>Utilize code generator and create a new scaffold for the <code>Product</code>:</p>
<pre><code>rails g scaffold Product title:string description:text
</code></pre><p>This should create a model, controller, routes, and views for the products. Don’t forget to run the migration:</p>
<pre><code>rails db:migrate
</code></pre><p>Now start the server:</p>
<pre><code>rails s
</code></pre><p>Visit the <code>http://localhost:3000/products</code> path and make sure that you are able to add, modify, and delete the products.</p>
<h3 id="heading-switching-the-language">Switching the Language</h3>
<p>In order to see the Globalize library in action, we will need a way to switch the app’s locale. I won’t cover this process in detail (as we have a <a target="_blank" href="https://blog.lokalise.co/rails-i18n/">separate article on the topic</a>) so let’s do it quickly.</p>
<p>First, add the list of supported locales to the <code>config/application.rb</code>:</p>
<pre><code># ... config.i18n.available_locales = [:en, :ru]
</code></pre><p>I will be supporting English and Russian, but you may choose any other languages.</p>
<p>Next, tweak the <code>config/routes.rb</code> and wrap the product resource with a scope. Also, while we are here, add a root route:</p>
<pre><code>scope <span class="hljs-string">"(:locale)"</span>, <span class="hljs-attr">locale</span>: <span class="hljs-regexp">/#{I18n.available_locales.join("|")}/</span> <span class="hljs-keyword">do</span> # &lt;== add <span class="hljs-built_in">this</span> resources :products root <span class="hljs-string">'products#index'</span> # &lt;== add <span class="hljs-built_in">this</span> end # &lt;== add <span class="hljs-built_in">this</span>
</code></pre><p>After that, modify the <code>application_controller.rb</code> file:</p>
<pre><code># ... before_action :set_locale private def set_locale I18n.locale = extract_locale || I18n.default_locale end def extract_locale parsed_locale = params[:locale] I18n.available_locales.map(&amp;:to_s).include?(parsed_locale) ? parsed_locale : nil end def default_url_options { <span class="hljs-attr">locale</span>: I18n.locale } end
</code></pre><p>This code will set the locale on every request while making sure the chosen language is actually supported. Also, it will add a <code>locale</code> GET param to each link generated with the <code>link_to</code> helper.</p>
<p>Lastly, add two links to the application layout:</p>
<pre><code>&lt;!-- views/layouts/application.html.erb --&gt; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">%=</span> <span class="hljs-attr">link_to</span> '<span class="hljs-attr">English</span>', <span class="hljs-attr">root_path</span>(<span class="hljs-attr">locale:</span> <span class="hljs-attr">:en</span>) %&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">%=</span> <span class="hljs-attr">link_to</span> 'Русский', <span class="hljs-attr">root_path</span>(<span class="hljs-attr">locale:</span> <span class="hljs-attr">:ru</span>) %&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>
</code></pre><p>To ensure that this new feature works, add translation for the Products page title:</p>
<pre><code># config/locales/en.yml en: products: index: title: Our Products
</code></pre><pre><code># config/locales/ru.yml ru: products: index: title: Наши продукты
</code></pre><p>Now simply utilize these translations inside the <code>views/products/index.html.erb</code>:</p>
<pre><code>&lt;!-- ... --&gt; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">%=</span> <span class="hljs-attr">t</span> '<span class="hljs-attr">.title</span>' %&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span> &lt;!-- ... --&gt;
</code></pre><p>Note that we can take advantage of the “lazy lookup” because the translation keys were named in the proper way.</p>
<p>Translate other static content as necessary, then reload the server, and make sure that the locale can be properly switched. Great!</p>
<h3 id="heading-globalize-globalize-it-hard">Globalize, Globalize it Hard!</h3>
<h4 id="heading-defining-attributes-for-translation">Defining Attributes For Translation</h4>
<p>Okay, the ground work is done and we may proceed to the next part. Before Globalize can get into the game, it should be added to the <code>Gemfile</code>:</p>
<pre><code># ... gem <span class="hljs-string">'globalize'</span>, <span class="hljs-attr">git</span>: <span class="hljs-string">'https://github.com/globalize/globalize'</span>
</code></pre><p>At the time of writing this article, the stable version was not yet compatible with Rails 5.2, so we have to install directly from the <code>master</code> branch. Also note that the latest stable does not support ActiveRecord 4.1 and below, therefore <a target="_blank" href="https://github.com/globalize/globalize#installation">refer to the documentation</a> to learn which Globalize version to use for older AR.</p>
<p>Next, you have to decide which model attributes will be translated with Globalize. We are going to translate both <code>:title</code> and <code>:description</code> so list them in the model in the following way:</p>
<pre><code># models/products.rb # ... translates :title, :description
</code></pre><p>This will allow you to store store translations inside the database per locale. To make it work, however, you also need to create a special <em>translation table</em>.</p>
<h4 id="heading-translation-table">Translation Table</h4>
<p>So, if you are creating a new model and a migration, things are as simple as using a <code>create_translation_table!</code> method as <a target="_blank" href="https://github.com/globalize/globalize#creating-translation-tables">explained here</a>. Our case is a bit more complex, because we already have a <code>products</code> table with some data. Therefore it is required to move these data to the translation table. Start by generating a new migration:</p>
<pre><code>rails g migration translate_products
</code></pre><p>Now flesh it out with the following code:</p>
<pre><code># db/migrate/xyz_translate_products.rb <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TranslateProducts</span> &lt; <span class="hljs-title">ActiveRecord</span>::<span class="hljs-title">Migration</span>[5.2] <span class="hljs-title">def</span> <span class="hljs-title">change</span> <span class="hljs-title">reversible</span> <span class="hljs-title">do</span> |<span class="hljs-title">dir</span>| # &lt;</span>=== <span class="hljs-number">1</span> dir.up <span class="hljs-keyword">do</span> Product.create_translation_table!({ # &lt;=== <span class="hljs-number">2</span> title: :string, # &lt;=== <span class="hljs-number">3</span> description: :text }, { <span class="hljs-attr">migrate_data</span>: <span class="hljs-literal">true</span>, # &lt;=== <span class="hljs-number">4</span> remove_source_columns: <span class="hljs-literal">true</span> # &lt;=== <span class="hljs-number">5</span> }) end dir.down <span class="hljs-keyword">do</span> Product.drop_translation_table! migrate_data: <span class="hljs-literal">true</span> # &lt;=== <span class="hljs-number">6</span> end end end end
</code></pre><p>I’ve pinpointed the main things to note about this code:</p>
<ol>
<li>This is going to be a reversible migration.</li>
<li>We are creating a translation table for the <code>Product</code>.</li>
<li>Carefully list all the fields that should be translated as well as their types. As you recall, these fields were passed to the <code>translates</code> method inside the model.</li>
<li>Don’t forget to provide the <code>migrate_data</code> option that should preserve your original database records.</li>
<li><code>remove_source_columns</code> will ensure that the original columns (<code>:title</code> and <code>:description</code>) will be removed from the <code>products</code> table. You may also perform this step later in a separate migration.</li>
<li>That’s the action to perform when the migration is rolled back. Data should be preserved as well.</li>
</ol>
<p>Run the migration:</p>
<pre><code>rails db:migrate
</code></pre><p>After this command finishes its job, you will see a new <code>product_translations</code> table:</p>
<p>As you see, there is a <code>product_id</code> column that establishes relation to the product, and also a <code>locale</code> field to denote which language this translation is for. When you migrate your original data, it will be associated with the app’s default locale (which is English in our case). Override this behavior by using a <code>with_locale</code> method, for example:</p>
<pre><code>I18n.with_locale(:ru) <span class="hljs-keyword">do</span> Post.create_translation_table!(...) end
</code></pre><p>If you need to add more translated fields to the table later, utilize an <code>add_translation_fields!</code> method <a target="_blank" href="https://github.com/globalize/globalize#adding-additional-fields-to-the-translation-table">as shown in this example</a>. Also, don’t forget to define these new fields in the model.</p>
<h4 id="heading-try-it">Try It!</h4>
<p>At this point Globalize is integrated into our application and ready to get rolling! Perform the following steps to see it in action:</p>
<ul>
<li>Reload your server and try to create a new product: its title and description will be provided for the currently set locale only (English in my case).</li>
<li>Switch to Russian locale and make sure that both title and description are missing for the new product.</li>
<li>Edit this product and enter values for the Russian version of the product.</li>
</ul>
<p>As a result you should see two translations being stored inside the <code>product_translations</code> table:</p>
<p>Great job!</p>
<h3 id="heading-some-more-globalize-features">Some More Globalize Features</h3>
<h4 id="heading-fallbacks">Fallbacks</h4>
<p>What happens if Globalize cannot find translated attributes for the given locale? As we’ve seen in the previous section, by default it will return blank values (which are actually <code>nil</code>s). However, it is possible to enable <a target="_blank" href="https://github.com/globalize/globalize#i18n-fallbacks-for-empty-translations">I18n fallbacks</a> and display attribute values from another locale. To achieve that, just turn fallbacks on inside the <code>config/application.rb</code> file:</p>
<pre><code># ... config.i18n.fallbacks = <span class="hljs-literal">true</span>
</code></pre><p>Now when the translated attribute is <code>nil</code>, Globalize will try to load values from another locale. To make sure this feature is working, reload the server, create a new product, and then switch to another language. The title and description should fallback to another locale.</p>
<p>If you would like to employ fallbacks when the translation values are also blank (not <code>nil</code>), set the <code>fallbacks_for_empty_translations</code> option to <code>true</code>:</p>
<pre><code># models/product.rb # ... translates :title, :description, <span class="hljs-attr">fallbacks_for_empty_translations</span>: <span class="hljs-literal">true</span>
</code></pre><p>Also note that it is possible to define a custom fallback chain globally in the following way:</p>
<pre><code># somewhere <span class="hljs-keyword">in</span> an initializer Globalize.fallbacks = {:<span class="hljs-function"><span class="hljs-params">en</span> =&gt;</span> [:de, :ru]}
</code></pre><h4 id="heading-scope-and-context">Scope and Context</h4>
<p>Globalize provides a special model scope called <code>with_translations</code> that can be used to load translation for a given language. In this example we are loading all translations for the English locale only:</p>
<pre><code>Product.with_translations(<span class="hljs-string">'en'</span>)
</code></pre><p>On top of that, it is possible to display translation for a desired locale in your views. To achieve that, use a <code>with_locale</code> method:</p>
<pre><code>&lt;% Globalize.with_locale(:en) <span class="hljs-keyword">do</span> %&gt; &lt;!-- render your stuff here... --&gt; &lt;% end %&gt;
</code></pre><h4 id="heading-interpolation">Interpolation</h4>
<p>What’s interesting is that Globalize even supports interpolation in the translated attributes. It works in the same way as interpolation in YAML translation files:</p>
<pre><code>product.title = <span class="hljs-string">"Product for %{someone}"</span> product.title someone: <span class="hljs-string">"John"</span> # =&gt; <span class="hljs-string">"Product for John"</span>
</code></pre><p>So, the placeholder here is <code>%{someone}</code>. To provide its value, simply pass a hash to the proper model attribute. Really convenient!</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>In this section we have seen how to store translations inside database with the help of Globalize solution. We have discussed its basics, seen how to install and configure it, how to migrate data properly, how to define translations, provide fallbacks and utilize scopes. All in all, we have covered nearly everything Globalize has to offer, and so you may now apply these concepts into practice! Also don’t forget that Globalize can safely play with YAML files, so you can mix and match these approaches as you see fit.</p>
<p>Which solution do you utilize to internationalize user-generated content? Would you give Globalize a go? Share your thoughts in the comments section!</p>
<h3 id="heading-make-your-life-easier-with-lokalise">Make Your Life Easier With Lokalise</h3>
<p>Supporting multiple languages on a big website may become a serious pain. You must make sure that all the keys are translated for each and every locale. Luckily, there is a solution to this problem: the Lokalise platform that <a target="_blank" href="https://lokalise.co/features">makes working with the localization files much simpler</a>. Let me guide you through the initial setup which is nothing complex really.</p>
<ul>
<li>To get started, <a target="_blank" href="https://lokalise.co/signup">grab your free trial</a></li>
<li>Create a new project, give it some name, and set English as a base language</li>
<li>Click “Upload Language Files”</li>
<li>Upload translation files for all your languages</li>
<li>Proceed to the project, and edit your translations as needed</li>
<li>You may also contact professional translator to do the job for you</li>
<li>Next simply download your files back</li>
<li>Profit!</li>
</ul>
<p>Lokalise has many more features including support for dozens of platforms and formats, and even the possibility to upload screenshots in order to read texts from them. So, stick with Lokalise and make your life easier!</p>
<p><em>Originally published at <a target="_blank" href="https://blog.lokalise.co/store-translations-inside-database-globalize/">blog.lokalise.co</a> on November 16, 2018.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to perform localization in Phoenix applications with Gettext ]]>
                </title>
                <description>
                    <![CDATA[ By Anastasia In my previous tutorial, we discussed how to introduce support for I18n into Rails apps. Today we will continue covering back-end frameworks and talk about localization of Phoenix applications with the help of Gettext. You might not have... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-perform-localization-in-phoenix-applications-with-gettext-c38bb0f01bef/</link>
                <guid isPermaLink="false">66c353e3d58e4fdd567d51c1</guid>
                
                    <category>
                        <![CDATA[ localization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ startup ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                    <category>
                        <![CDATA[ translation ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 27 Sep 2018 06:46:25 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*9FLnNCwPgLPZBvQ4pfwnzg.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Anastasia</p>
<p>In my previous tutorial, we discussed <a target="_blank" href="https://blog.lokalise.co/rails-i18n/">how to introduce support for I18n into Rails apps</a>. Today we will continue covering back-end frameworks and talk about <em>localization of Phoenix applications</em> with the help of <em>Gettext</em>.</p>
<p>You might not have heard about <a target="_blank" href="http://phoenixframework.org/">Phoenix</a> before, so let me say a couple of words about it. This is a server-side MVC framework written in <a target="_blank" href="https://elixir-lang.org/">Elixir</a>, which is a functional programming language working on <a target="_blank" href="https://en.wikipedia.org/wiki/BEAM_(Erlang_virtual_machine)">Erlang virtual machine</a>. The framework itself is quite young but still it is very promising thanks to Erlang’s and Elixir’s features. It is very fast, scalable, and concurrency-oriented which is really important for heavily loaded applications.</p>
<p><a target="_blank" href="https://www.gnu.org/software/gettext/manual/gettext.html#Why">Gettext</a>, in turn, is an I18n tool maintained by GNU which may be used for web, desktop applications, and even in operating systems.</p>
<p>Throughout this article we will be localizing a Phoenix demo project and will see Gettext in action. Also, we will discuss how to introduce support for locale switching and persisting user preferences throughout the requests. Before proceeding to the main part of the tutorial, you also might want to learn common recommendations <a target="_blank" href="https://blog.lokalise.co/localization-5-focus-points/">which are listed in our recent article</a>.</p>
<h3 id="heading-hello-gettext">Hello, Gettext!</h3>
<p>Alright, let’s dive straight into the code and observe the localization of Phoenix applications in practice. Create a new project without a default DBMS and change directory into the project:</p>
<pre><code>mix phx.new lokalise_demo --no-ecto cd lokalise_demo
</code></pre><p>It appears that Phoenix has support for Gettext out of the box: you don’t need to install any third-party libraries. Moreover, if you navigate to the <code>demo/lib/demo_web/templates/page/index.html.eex</code> file, you’ll notice the following line of code:</p>
<pre><code>&lt;h2&gt;&lt;%= gettext <span class="hljs-string">"Welcome to %{name}!"</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">"Phoenix"</span> %&gt;&lt;/h2&gt;
</code></pre><p>What is going on here? Well, <code>gettext</code> <a target="_blank" href="https://hexdocs.pm/gettext/Gettext.html#gettext/2">is a function</a> that tries to load translation for the string <code>"Welcome to %{name}!"</code>. <code>%{name}</code> here is a <a target="_blank" href="https://hexdocs.pm/gettext/Gettext.html#module-interpolation">placeholder that will be replaced</a> with a <code>"Phoenix"</code> string as dictated by the second argument <code>name: "Phoenix"</code> (this argument contains so-called <em>bindings</em>).</p>
<p>By default, Phoenix applications have English as the default locale set, and no other locales are supported. However, you may easily change that by adding a new line to the <code>config/config.exs</code> file:</p>
<pre><code>config :lokalise_demo, LokaliseDemoWeb.Gettext, <span class="hljs-attr">locales</span>: ~w(en ru)
</code></pre><p>Now we are supporting both English and Russian locales.</p>
<p>The next step is to provide translations for the string passed to the <code>gettext</code> function inside the <code>index.html.eex</code> file. The simplest way to do that is by extracting all translation strings into separate files automatically:</p>
<pre><code>mix gettext.extract mix gettext.merge priv/gettext mix gettext.merge priv/gettext --locale ru
</code></pre><p>These commands are going to create three new files inside the <code>priv/gettext</code> folder. Therefore, let’s stop for a second and talk a bit more about these files.</p>
<h3 id="heading-gettext-file-types">Gettext File Types</h3>
<p>The first command above, <code>mix gettext.extract</code>, searches for all Gettext messages that require translation and places them into the <code>priv/gettext/default.pot</code> file. POT means “portable object template”, and such files serve as templates for language-specific translations. Our <code>default.pot</code> has the following contents:</p>
<pre><code>## This file is a PO Template file. ## ## msgid here are often extracted <span class="hljs-keyword">from</span> source code. ## Add <span class="hljs-keyword">new</span> translations manually only <span class="hljs-keyword">if</span> they<span class="hljs-string">'re dynamic ## translations that can'</span>t be statically extracted. ## ## Run mix gettext.extract to bring <span class="hljs-built_in">this</span> file up to ## date. Leave msgstr empty <span class="hljs-keyword">as</span> changing them here <span class="hljs-keyword">as</span> no ## effect: edit them <span class="hljs-keyword">in</span> PO (.po) files instead. msgid <span class="hljs-string">""</span> msgstr <span class="hljs-string">""</span> #, elixir-format #: lib/lokalise_demo_web/templates/page/index.html.eex:<span class="hljs-number">2</span> msgid <span class="hljs-string">"Welcome to %{name}!"</span> msgstr <span class="hljs-string">""</span>
</code></pre><p>The template conveniently shows the lines where the extracted messages are located. <code>msgid</code> is the string to translate (some developers may refer to it as a “key”). <code>msgstr</code> is, of course, the actual translation.</p>
<p>The name of the POT file — <code>default</code> — is also a <a target="_blank" href="https://hexdocs.pm/gettext/Gettext.html#module-domains"><em>domain name</em></a> which serves as a namespace. Initially, there is only one namespace, but for larger sites with hundreds of translations it may be a good idea to create multiple domains and, consequently, separate translations into different files.</p>
<p>The <code>mix gettext.merge priv/gettext --locale LOCALE_CODE_HERE</code> command creates <a target="_blank" href="https://hexdocs.pm/gettext/Gettext.html#module-translations">translation files</a> for the given language based on the template. These translation files have <code>.po</code> extension (“portable object”) and live inside the <code>priv/gettext/LOCALE_CODE_HERE/LC_MESSAGES</code> folder. Remember that in order to provide translations for the messages, you should edit these PO files, not the templates directly!</p>
<h3 id="heading-gettext-domains">Gettext Domains</h3>
<p>As already mentioned above, Gettext supports multiple domains or namespaces. When you are utilizing the <code>gettext/4</code> function, you always assume a <code>default</code> domain. If you would like to employ a different namespace, use the <code>[dgettext/6](https://hexdocs.pm/gettext/Gettext.html#dngettext/6)</code> <a target="_blank" href="https://hexdocs.pm/gettext/Gettext.html#dngettext/6">function</a> instead which accepts the domain, the message, optional bindings, and some other arguments:</p>
<pre><code>&lt;%= dgettext <span class="hljs-string">"custom_domain"</span>, <span class="hljs-string">"message is ${placeholder}"</span>, <span class="hljs-attr">placeholder</span>: <span class="hljs-string">"my binding"</span> %&gt;
</code></pre><p>Now the <code>mix gettext.extract</code> command is going to create a new <code>custom_domain.pot</code> file. Similarly, running <code>mix gettext.merge</code> creates a <code>custom_domain.po</code> file based on the template.</p>
<p>Note once again that for smaller sites, using multiple domains is usually an overkill. Still, their usage for large resources is very much recommended because this way you don’t end up with hundreds of translations in a single file. Another reason is the ability to have the same translation keys under different namespaces.</p>
<h3 id="heading-providing-translations">Providing Translations</h3>
<p>So, having discussed some Gettext internals, we can now translate the <code>Welcome to %{name}!</code> string into Russian (this message is already in English, so of course no translation is needed for this language). Modify the <code>priv/gettext/ru/LC_MESSAGES/default.po</code> file like this:</p>
<pre><code># ... some other stuff goes here ... #, elixir-format #: lib/lokalise_demo_web/templates/page/index.html.eex:<span class="hljs-number">2</span> msgid <span class="hljs-string">"Welcome to %{name}!"</span> msgstr <span class="hljs-string">"Вас приветствует %{name}"</span>
</code></pre><p>This is it! Currently we do not have any mechanism to switch the language, so set Russian as a <a target="_blank" href="https://hexdocs.pm/gettext/Gettext.html#module-default-locale">default locale</a>:</p>
<pre><code># config/config.exs config :lokalise_demo, LokaliseDemoWeb.Gettext, <span class="hljs-attr">locales</span>: ~w(en ru), <span class="hljs-attr">default_locale</span>: <span class="hljs-string">"ru"</span> # &lt;== modify <span class="hljs-built_in">this</span> line
</code></pre><p>Now start the server by running:</p>
<pre><code>mix phx.server
</code></pre><p>Open <code>http://localhost:4000</code> page in your browser and make sure that the translated message is shown!</p>
<h3 id="heading-gettext-pluralization">Gettext Pluralization</h3>
<p>Another important feature that I would like to cover is the <a target="_blank" href="https://hexdocs.pm/gettext/Gettext.html#module-pluralization">pluralization</a>. Different languages have different pluralization rules, and Gettext supports many of them out of the box. Still, it is our job to provide proper translations for all potential cases.</p>
<p>As a very simple example, let’s say how many apples the user has. Suppose we don’t know the exact amount, which means that the sentence may read as “1 apple” or “X apples”. To support pluralization, we have to stick with the <code>[ngettext/5](https://hexdocs.pm/gettext/Gettext.html#ngettext/5)</code> <a target="_blank" href="https://hexdocs.pm/gettext/Gettext.html#ngettext/5">function</a>:</p>
<pre><code>ngettext <span class="hljs-string">"You have 1 apple"</span>, <span class="hljs-string">"You have %{count} apples"</span>, <span class="hljs-number">2</span>
</code></pre><p>This function accepts both singular and plural forms of the sentence, as well as the <code>count</code>. Under the hood, Gettext takes this count and chooses the proper translation based on the pluralization rules.</p>
<p>Next you may update the POT and PO files with the following commands:</p>
<pre><code>mix gettext.extract --merge priv/gettext mix gettext.extract --merge priv/gettext --locale=ru
</code></pre><p>You’ll find a couple of new lines inside the Gettext files:</p>
<pre><code>msgid <span class="hljs-string">"You have 1 apple"</span> msgid_plural <span class="hljs-string">"You have %{count} apples"</span> msgstr[<span class="hljs-number">0</span>] <span class="hljs-string">""</span> msgstr[<span class="hljs-number">1</span>] <span class="hljs-string">""</span>
</code></pre><p><code>msgstr[0]</code> and <code>msgstr[1]</code> contain translations for singular and plural forms respectively. For English we don’t need to do anything else, but the Russian language requires some extra steps:</p>
<pre><code>msgid <span class="hljs-string">"You have one message"</span> msgid_plural <span class="hljs-string">"You have %{count} messages"</span> msgstr[<span class="hljs-number">0</span>] <span class="hljs-string">"У вас одно яблоко"</span> msgstr[<span class="hljs-number">1</span>] <span class="hljs-string">"У вас %{count} яблока"</span> msgstr[<span class="hljs-number">2</span>] <span class="hljs-string">"У вас %{count} яблок"</span>
</code></pre><p>The pluralization rules in this case are a bit more complex, therefore we must provide not two, but three possible options. You may find more information on the topic <a target="_blank" href="https://hexdocs.pm/gettext/Gettext.Plural.html">in the official docs</a>.</p>
<h3 id="heading-choosing-the-apps-locale">Choosing The App’s Locale</h3>
<p>As I already mentioned earlier, currently there is no way to actually switch between locales when browsing the app. This is an important feature, so let’s add it now!</p>
<p>All in all, we have two potential solutions:</p>
<ul>
<li>Utilize a third-party solution, for example the <a target="_blank" href="https://github.com/smeevil/set_locale">set_locale</a> plug (the easy way)</li>
<li>Write everything from scratch (the warrior’s way)</li>
</ul>
<p>If you choose to stick with the third-party plug, things will be very simple indeed. You need to perform <a target="_blank" href="https://github.com/smeevil/set_locale#setup">only three quick steps</a>:</p>
<ol>
<li>Install the package</li>
<li>Add a new plug to the <code>router.ex</code> file</li>
<li>Add a new <code>:locale</code> routing scope</li>
</ol>
<p>After that the <a target="_blank" href="https://github.com/smeevil/set_locale#fallback-chain-and-precedence">locale will be inferred</a> from the URL, cookies, or the <code>accept-language</code> request header. Simple.</p>
<p>However, in this tutorial I propose choosing a more complex way and writing this feature from scratch.</p>
<h3 id="heading-reading-locale-from-the-url">Reading Locale From the URL</h3>
<p>The most common way of specifying the desired locale is via the URL. The language’s code may be a part of the domain name, or a part of the path:</p>
<ul>
<li><code>[http://en.example.com/some/path](http://en.example.com/some/path)</code></li>
<li><code>[http://example.com/en/some/path](http://example.com/en/some/path)</code></li>
<li><code>[http://example.com/some/path?locale=en](http://example.com/some/path?locale=en)</code></li>
</ul>
<p>Let’s stick with the latter option and provide the locale as a GET parameter. To read the locale’s value and do something about it, we need a <a target="_blank" href="https://hexdocs.pm/phoenix/plug.html#module-plugs">custom plug</a>. Create a new <code>lib/lokalise_demo_web/plugs/set_locale_plug.ex</code> file with the following contents:</p>
<pre><code>defmodule LokaliseDemoWeb.Plugs.SetLocale <span class="hljs-keyword">do</span> <span class="hljs-keyword">import</span> Plug.Conn # <span class="hljs-number">1</span> @supported_locales Gettext.known_locales(LokaliseDemoWeb.Gettext) # <span class="hljs-number">2</span> def init(_options), <span class="hljs-attr">do</span>: nil # <span class="hljs-number">3</span> def call(%Plug.Conn{<span class="hljs-attr">params</span>: %{<span class="hljs-string">"locale"</span> =&gt; locale}} = conn, _options) when locale <span class="hljs-keyword">in</span> @supported_locales <span class="hljs-keyword">do</span> # <span class="hljs-number">4</span> end def call(conn, _options), <span class="hljs-attr">do</span>: conn # <span class="hljs-number">5</span> end
</code></pre><p>Let’s discuss this code snippet:</p>
<ol>
<li>On this line we are importing a behavior. It requires us to fulfill a certain contract (see below).</li>
<li>This is the module attribute with a list of supported locales</li>
<li>This is the actual fulfillment of the contract: a callback that gets invoked automatically. It may return options passed to the <code>call/2</code> function, or just <code>nil</code></li>
<li>The <code>call/2</code> is initialized with all the GET parameters of the request. We are only interested in the <code>locale</code> part and fetch it using the pattern matching mechanism. Also on this line we have a guard clause that ensures the chosen language is actually supported</li>
<li>This is the fallback clause that gets invoked when the passed locale is unsupported. In this case we just return the connection without any modifications.</li>
</ol>
<p>The last thing we need to do is flesh out the first clause of the <code>call/2</code> function. It simply has to set the chosen locale as the current one:</p>
<pre><code>def call(%Plug.Conn{<span class="hljs-attr">params</span>: %{<span class="hljs-string">"locale"</span> =&gt; locale}} = conn, _options) when locale <span class="hljs-keyword">in</span> @supported_locales <span class="hljs-keyword">do</span> LokaliseDemoWeb.Gettext |&gt; Gettext.put_locale(locale) conn end
</code></pre><p>Note that the <code>conn</code> must be returned by the <code>call/2</code> function!</p>
<p>The plug is ready, and you may place it inside the <code>:browser</code> pipeline:</p>
<pre><code># lib/router.ex # ... pipeline :browser <span class="hljs-keyword">do</span> plug :accepts, [<span class="hljs-string">"html"</span>] plug :fetch_session plug :fetch_flash plug :protect_from_forgery plug :put_secure_browser_headers plug LokaliseDemoWeb.Plugs.SetLocale end
</code></pre><p>Now reload the server and navigate to <code>http://localhost:4000/?locale=en</code>. The welcoming message should be in English which means that the custom plug is working as expected!</p>
<h3 id="heading-storing-locale-into-a-cookie">Storing Locale Into a Cookie</h3>
<p>Our next task is persisting the chosen locale among requests so that the user does not need to provide it every time. The perfect candidate for such persistence would be cookies: small text files stored on the user’s PC. Phoenix indeed has support for cookies out of the box, so just utilize a <code>[put_resp_cookies/4](https://hexdocs.pm/plug/Plug.Conn.html#put_resp_cookie/4)</code> <a target="_blank" href="https://hexdocs.pm/plug/Plug.Conn.html#put_resp_cookie/4">function</a> inside your plug:</p>
<pre><code>def call(%Plug.Conn{<span class="hljs-attr">params</span>: %{<span class="hljs-string">"locale"</span> =&gt; locale}} = conn, _options) when locale <span class="hljs-keyword">in</span> @supported_locales <span class="hljs-keyword">do</span> LokaliseDemoWeb.Gettext |&gt; Gettext.put_locale(locale) conn |&gt; put_resp_cookie <span class="hljs-string">"locale"</span>, locale, <span class="hljs-attr">max_age</span>: <span class="hljs-number">365</span>*<span class="hljs-number">24</span>*<span class="hljs-number">60</span>*<span class="hljs-number">60</span> end
</code></pre><p>We modify the connection by storing a cookie named <code>"locale"</code>. It has a lifetime of 1 year which effectively means eternity in terms of the web.</p>
<p>The last step here is reading the chosen locale from the cookie. Unfortunately, we cannot use a guard clause for this task anymore, so let’s replace two clauses of the <code>call/2</code> function with only one:</p>
<pre><code>def call(conn, _options) <span class="hljs-keyword">do</span> <span class="hljs-keyword">case</span> fetch_locale_from(conn) <span class="hljs-keyword">do</span> nil -&gt; conn locale -&gt; LokaliseDemoWeb.Gettext |&gt; Gettext.put_locale(locale) conn |&gt; put_resp_cookie <span class="hljs-string">"locale"</span>, locale, <span class="hljs-attr">max_age</span>: <span class="hljs-number">365</span>*<span class="hljs-number">24</span>*<span class="hljs-number">60</span>*<span class="hljs-number">60</span> end end
</code></pre><p>All in all, the logic remains the same: we fetch the locale, check it, and then either do nothing or store it as the current one.</p>
<p>Add two private functions to finalize this feature:</p>
<pre><code>defp fetch_locale_from(conn) <span class="hljs-keyword">do</span> (conn.params[<span class="hljs-string">"locale"</span>] || conn.cookies[<span class="hljs-string">"locale"</span>]) |&gt; check_locale end defp check_locale(locale) when locale <span class="hljs-keyword">in</span> @supported_locales, <span class="hljs-attr">do</span>: locale defp check_locale(_), <span class="hljs-attr">do</span>: nil
</code></pre><p>Here we are reading the locale from the either the GET param or cookie, and then checking if the desired language is supported. Then either return this language’s code, or just <code>nil</code>. Great job!</p>
<p>Another pretty common way of setting the locale is by using the <code>Accept-Language</code> HTTP header. If you would like to implement this mechanism, try utilizing <a target="_blank" href="https://github.com/smeevil/set_locale/blob/fd35624e25d79d61e70742e42ade955e5ff857b8/lib/headers.ex">the code from the set_locale plug</a> that already provides all the necessary RegExs and other fancy stuff.</p>
<h3 id="heading-locale-switcher-control">Locale Switcher Control</h3>
<p>So, the <code>SetLocale</code> plug is ready, but we still have not provided any controls to choose the website’s language. Therefore, let’s render two links at the top of the page. Define a new helper inside the <code>lib/views/layout_view.ex</code> file:</p>
<pre><code>defmodule LokaliseDemoWeb.LayoutView <span class="hljs-keyword">do</span> use LokaliseDemoWeb, :view def new_locale(conn, locale, language_title) <span class="hljs-keyword">do</span> <span class="hljs-string">"&lt;a href=\"#{page_path(conn, :index, locale: locale)}\"&gt;#{language_title}&lt;/a&gt;"</span> |&gt; raw end end
</code></pre><p>Call this helper from the <code>templates/layout/app.html.eex</code> template:</p>
<pre><code>&lt;body&gt; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"container"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">header</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"header"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">%=</span> <span class="hljs-attr">new_locale</span> @<span class="hljs-attr">conn</span>, <span class="hljs-attr">:en</span>, "<span class="hljs-attr">English</span>" %&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">%=</span> <span class="hljs-attr">new_locale</span> @<span class="hljs-attr">conn</span>, <span class="hljs-attr">:ru</span>, "<span class="hljs-attr">Russian</span>" %&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">header</span>&gt;</span> <span class="hljs-comment">&lt;!-- other stuff --&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span> &lt;/body&gt;
</code></pre><p>Reload the page and try switching between locales. Everything should be working just fine, which means that the task is completed!</p>
<h3 id="heading-simplify-your-life-with-lokalise">Simplify Your Life With Lokalise</h3>
<p>By now you are probably thinking that supporting multiple languages on a big website is probably a pain. And, honestly, you are right. Of course, the translations can be namespaced with the help of domains. But still you must make sure that all the keys are translated for each and every locale. Luckily, there is a solution to this problem: the Lokalise platform that <a target="_blank" href="https://lokalise.co/features">makes working with the localization files much simpler</a>. Let me guide you through the initial setup which is nothing complex really.</p>
<ul>
<li>To get started, <a target="_blank" href="https://lokalise.co/signup">grab your free trial</a></li>
<li>Create a new project, give it some name, and set English as a base language</li>
<li>Click “Upload Language Files”</li>
<li>Upload PO files for all your languages</li>
<li>Proceed to the project, and edit your translations as needed</li>
<li>You may also contact professional translator to do the job for you</li>
<li>Next simply download your PO files back and replace them inside the <code>priv/gettext</code> folder</li>
<li>Profit!</li>
</ul>
<p>Lokalise has many more features including support for dozens of platforms and formats, and even the possibility to upload screenshots in order to read texts from them. So, stick with Lokalise and make your life easier!</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>In today’s tutorial we have seen how to perform localization of Phoenix applications with the help of Gettext. We have discussed what Gettext is and what goodies it has to offer. We have seen how to extract translations, generate templates, and create PO files based on these templates. You have also learned what domains are, and how to introduce support for pluralization. On top of that, we have successfully created our custom plug to fetch and persist the chosen locale based on the user’s preferences. Not bad for one article!</p>
<p>To learn more about Phoenix I18n, I encourage you to check out <a target="_blank" href="https://hexdocs.pm/gettext/Gettext.html">the official guide</a> that provides both general explanations, as well as documentation for individual functions. To learn about the Gettext and its features in more detail, refer to the <a target="_blank" href="https://www.gnu.org/software/gettext/manual/gettext.html">GNU’s documentation</a>. And, of course, if you have any questions feel free to post them in the comments!</p>
<p><em>Originally published at <a target="_blank" href="https://blog.lokalise.co/localization-of-phoenix-applications/">blog.lokalise.co</a> on September 27, 2018.</em></p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
