<?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[ App Localization - 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[ App Localization - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 28 Jul 2026 11:53:09 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/app-localization/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Svelte i18n and Localization Made Easy ]]>
                </title>
                <description>
                    <![CDATA[ Apps are accessible worldwide. This means anyone from anywhere in the world can download your app.  So, if you want to cater to people everywhere, your app needs to support multiple languages.  Fortunately, Svelte is easy to work with, and it makes l... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/svelte-i18n-and-localization-made-easy/</link>
                <guid isPermaLink="false">6752020830d899211b5bda58</guid>
                
                    <category>
                        <![CDATA[ localization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Svelte ]]>
                    </category>
                
                    <category>
                        <![CDATA[ i18n ]]>
                    </category>
                
                    <category>
                        <![CDATA[ app development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ App Localization ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Alex Tray ]]>
                </dc:creator>
                <pubDate>Thu, 05 Dec 2024 19:42:00 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1733421094910/f2f91ab6-0717-4135-9f08-719f041471f6.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Apps are accessible worldwide. This means anyone from anywhere in the world can download your app. </p>
<p>So, if you want to cater to people everywhere, your app needs to support multiple languages. </p>
<p>Fortunately, Svelte is easy to work with, and it makes localization (l10n) and internationalization (i18n) quite straightforward. </p>
<p>But it lacks built-in i18n support—so you need to use a library like svelte-i18n or one of the others available. Let’s create a simple Svelte app to demonstrate how localization can be implemented. </p>
<p>We’ll create a welcome screen that can be used in both English and Spanish and then build some more advanced features.</p>
<dl>
<summary>Table of Contents</summary>
<ul>
<li>
  <a href="heading-what-makes-svelte-unique">What Makes Svelte Unique?</a></li>
  <li><a href="heading-how-to-localize-a-svelte-application">How to Localize a Svelte Application?</a></li>
  <li><a href="heading-adding-language-support">Adding Language Support</a></li>
  <li><a href="heading-updating-components-to-use-translations">Updating Components to Use Translations</a></li>
  <li><a href="heading-creating-a-language-switcher">Creating a Language Switcher</a></li>
  <li><a href="heading-adding-advanced-features">Adding Advanced Features</a></li>
<details>
  <li><a href="heading-formatting-numbers-and-currencies">Formatting Numbers and Currencies</a></li>
  <li><a href="heading-formatting-dates">Formatting Dates</a></li>
  <li><a href="heading-localizing-images">Localizing Images</a></li>
<details>
  <li><a href="heading-dynamic-image-paths">Dynamic Image Paths</a></li><li>
  </li><li><a href="heading-integrating-alternative-text-localization">Integrating Alternative Text Localization</a></li>
 <li><a href="heading-switching-svg-content-dynamically">Switching SVG Content Dynamically</a></li>
</details>
  <li><a href="heading-handling-multiple-forms-of-pluralization">Handling Multiple Forms of Pluralization</a></li>
  <li><a href="heading-handling-missing-translations">Handling Missing Translations</a></li>
</details>
  <li><a href="heading-making-your-app-production-ready">Making Your App Production-Ready</a></li>
 <li><a href="heading-best-practices-for-scaling-your-localization">Best Practices for Scaling Your Localization</a></li>
  <li><a href="heading-wrapping-up">Wrapping Up</a></li>
</ul>
</dl>

<h2 id="heading-what-makes-svelte-unique">What Makes Svelte Unique?</h2>
<p>Similar to <a target="_blank" href="https://centus.com/blog/vue-i18n">Vue i18n</a>, Svelte converts code to vanilla JS during the build process. This means your app ships with minimal code and offers excellent performance.</p>
<p>While other frameworks like React and Vue have longer startup times, Svelte’s compilation process changes that. It creates much smaller bundles, and apps run faster by default.</p>
<p>Svelte’s reactive syntax and lightweight nature make it an excellent choice for developers who want efficient, modern applications. </p>
<p>Its minimalism aligns well with the simplicity required in <a target="_blank" href="https://v2cloud.com/blog/best-programming-languages-for-cloud-computing"><strong>cloud development languages</strong></a>, ensuring that applications are lean, scalable, and optimized for cloud environments. </p>
<p>This minimalism also means you may not always have all the required built-in features. But pretty much all the limitations are resolved with the help of external libraries. </p>
<h2 id="heading-how-to-localize-a-svelte-application">How to Localize a Svelte Application</h2>
<p>Let’s jump right into creating a Svelte project now. I’ll create the project using the <code>npm create</code> command. Run the below commands one by one:</p>
<pre><code class="lang-javascript">npm create svelte@latest freecodecamp-localization-demo
cd freecodecamp-localization-demo
npm install
npm install svelte-i18n
</code></pre>
<p>The <code>npm create</code> command will prompt you with a few choices. Here’s what I’ve picked (but you can always adjust this based on your project requirements):</p>
<ul>
<li><p>Skeleton project: Select <strong>Yes</strong>.</p>
</li>
<li><p>Add TypeScript support: Select <strong>No</strong> (or Yes if you prefer TypeScript).</p>
</li>
<li><p>Add ESLint for code linting: Select <strong>Yes</strong>.</p>
</li>
<li><p>Add Prettier for code formatting: Select <strong>Yes</strong>.</p>
</li>
</ul>
<p>Now that we have our project set up, let's create a welcome component that we'll later enhance with translations. </p>
<p>Create a new file called Welcome.svelte in your src directory:</p>
<pre><code class="lang-javascript">&lt;!-- src/Welcome.svelte --&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> username;
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Welcome {username}!<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfcaW7fLzjbLa5ysYYu5FplhoGeVNmml9An_l0fcbEwQSxvg5mDbh3PY9b7etS6DESM7ZGdO_R5dqcYaDdgMaaQE2d7w1Q8eU4uAtIfKjHfm58buFwM-KLtJ_bv-x3XyqoYIOgfdQ?key=uXnvRGfJpBUiBb7CkgThtLro" alt="AD_4nXfcaW7fLzjbLa5ysYYu5FplhoGeVNmml9An_l0fcbEwQSxvg5mDbh3PY9b7etS6DESM7ZGdO_R5dqcYaDdgMaaQE2d7w1Q8eU4uAtIfKjHfm58buFwM-KLtJ_bv-x3XyqoYIOgfdQ?key=uXnvRGfJpBUiBb7CkgThtLro" width="1416" height="578" loading="lazy"></p>
<p>This component takes the username property (that I’ve passed from the App.svelte file) and displays a welcome message. </p>
<p>Simple enough for now, but what if your users speak different languages? Let’s add language support.</p>
<h2 id="heading-adding-language-support">Adding Language Support</h2>
<p>To do this, we need to create translation files for each language. Start by creating a new directory called <strong>locales</strong> in your <strong>src</strong> folder. Inside the <strong>locales</strong> folder, create two JSON files—<em>en.json</em> for English and <em>es.json</em> for Spanish.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// src/locales/en.json</span>
{
  <span class="hljs-string">"hello"</span>: <span class="hljs-string">"Hello {username}!"</span>,
  <span class="hljs-string">"buttons"</span>: {
    <span class="hljs-string">"save"</span>: <span class="hljs-string">"Save"</span>,
    <span class="hljs-string">"cancel"</span>: <span class="hljs-string">"Cancel"</span>
  }
}

<span class="hljs-comment">// src/locales/es.json  </span>
{
  <span class="hljs-string">"hello"</span>: <span class="hljs-string">"¡Hola {username}!"</span>,
  <span class="hljs-string">"buttons"</span>: {
    <span class="hljs-string">"save"</span>: <span class="hljs-string">"Guardar"</span>,
    <span class="hljs-string">"cancel"</span>: <span class="hljs-string">"Cancelar"</span>
  }
}
</code></pre>
<p>These files contain our translation strings.</p>
<p>Notice how we've organized them in a nested structure—this helps manage translations as your app grows. </p>
<p>The {username} and {count} placeholders will be replaced with actual values during runtime when we dynamically (or statically) pass the required values.</p>
<p>Next, we need to tell Svelte how to use these translations. For this, we need an <strong>i18n configuration</strong> file:</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// src/i18n.js</span>
<span class="hljs-keyword">import</span> { register, init } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte-i18n'</span>;

register(<span class="hljs-string">'en'</span>, <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./locales/en.json'</span>));
register(<span class="hljs-string">'es'</span>, <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./locales/es.json'</span>));

init({
  <span class="hljs-attr">fallbackLocale</span>: <span class="hljs-string">'en'</span>,
  <span class="hljs-attr">initialLocale</span>: <span class="hljs-string">'en'</span>,
});
</code></pre>
<p>We’ve registered our translation files and set English as both the initial language and fallback language. The fallback language is used when a translation is missing in the selected language.</p>
<h2 id="heading-updating-components-to-use-translations">Updating Components to Use Translations</h2>
<p>Now we can update our welcome component to use the text from the JSON file:</p>
<pre><code class="lang-javascript">&lt;!-- src/Welcome.svelte --&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> {  } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte-i18n'</span>;
  <span class="hljs-keyword">export</span> <span class="hljs-keyword">let</span> username;
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>{$('hello', { username })}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>The <code>$_</code> function is a special helper from svelte-i18n that retrieves translated strings. </p>
<p>When we pass { username } as the second argument, it replaces the placeholder in our translation strings with the actual username.</p>
<h2 id="heading-creating-a-language-switcher">Creating a Language Switcher</h2>
<p>How would someone change the language, though? Let's create a simple language selector component:</p>
<pre><code class="lang-javascript">&lt;!-- src/LanguageSelect.svelte --&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { locale } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte-i18n'</span>;

  <span class="hljs-keyword">const</span> languages = [
    { <span class="hljs-attr">code</span>: <span class="hljs-string">'en'</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'English'</span> },
    { <span class="hljs-attr">code</span>: <span class="hljs-string">'es'</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Español'</span> }
  ];
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
  {#each languages as { code, name }}
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> locale.set(code)}&gt;{name}<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  {/each}
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p>The <strong>bind:value</strong> directive automatically updates the active language when users make a selection. </p>
<p>The locale store from svelte-i18n handles all the behind-the-scenes work of switching languages.</p>
<p>Now let's bring everything together in our main <strong>App</strong> component:</p>
<pre><code class="lang-javascript">&lt;!-- src/App.svelte --&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { waitLocale } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte-i18n'</span>;
  <span class="hljs-keyword">import</span> Welcome <span class="hljs-keyword">from</span> <span class="hljs-string">'./Welcome.svelte'</span>;
  <span class="hljs-keyword">import</span> LanguageSelect <span class="hljs-keyword">from</span> <span class="hljs-string">'./LanguageSelect.svelte'</span>;

  <span class="hljs-keyword">const</span>  username = <span class="hljs-string">'developer'</span>;
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>

{#<span class="hljs-keyword">await</span> waitLocale()}
  &lt;p&gt;Loading...&lt;/p&gt;
{:then}
  &lt;main&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">LanguageSelect</span> /&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Welcome</span> {<span class="hljs-attr">username</span>} /&gt;</span></span>
  &lt;/main&gt;
{/<span class="hljs-keyword">await</span>}
</code></pre>
<p>The <code>waitLocale</code> function ensures translations are loaded before showing content. This prevents flickering or missing translations when the app first loads.</p>
<h2 id="heading-adding-advanced-features">Adding Advanced Features</h2>
<p>As your app grows, you'll need to handle more complex scenarios. Let's look at some common requirements.</p>
<h3 id="heading-formatting-numbers-and-currencies">Formatting Numbers and Currencies</h3>
<p>Different countries handle numbers and currencies quite differently. So for instance, if you show the figure of a hundred thousand to someone from France, and someone from the USA, you’ll need to show the same figure differently. </p>
<p>France → 100 000,00 $</p>
<p>USA → $100,000.00</p>
<p>You see how the thousands are separated by a space and the decimal by a comma in France? Using the US number format will make it quite confusing for someone from France. Here are a few other examples.</p>
<ul>
<li><p>US uses periods for decimals (1,234.56)</p>
</li>
<li><p>Many European countries use commas for decimals and periods for thousands (1.234,56)</p>
</li>
<li><p>Some countries group digits differently (like 1,23,456 in India)</p>
</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// src/lib/formatUtils.js</span>
<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">formatCurrency</span>(<span class="hljs-params">amount, locale, currency = <span class="hljs-string">'USD'</span></span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Intl</span>.NumberFormat(locale, {
    <span class="hljs-attr">style</span>: <span class="hljs-string">'currency'</span>,
    currency
  }).format(amount);
}
</code></pre>
<p>You can now use these formatters in your components:</p>
<pre><code class="lang-javascript">&lt;!-- src/lib/PriceDisplay.svelte --&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { formatCurrency } <span class="hljs-keyword">from</span> <span class="hljs-string">'./lib/formatUtils'</span>;
  <span class="hljs-keyword">let</span> price = <span class="hljs-number">1234.56</span>;
  <span class="hljs-keyword">let</span> locale = <span class="hljs-string">'en'</span>;
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Price: {formatCurrency(price, locale, 'USD')}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
</code></pre>
<p>With this setup, the app now adapts the currency formats to the different locales based on what outputs you ask from it:</p>
<ul>
<li><p>US: "$1,234.56", "1.2M", "15%"</p>
</li>
<li><p>German: "1.234,56 €", "1,2 Mio.", "15 %"</p>
</li>
</ul>
<h3 id="heading-formatting-dates">Formatting Dates</h3>
<p>Similar to currency and number formats, date are formatted differently across different locales. </p>
<p>So, while the US uses MM/DD/YYYY, many European countries use DD/MM/YYYY, and Japan often uses YYYY年MM月DD日. </p>
<p>Luckily, we don’t need to handle this manually. Similar to currency formatting, we have the <code>Intl.DateTimeFormat</code> function that accepts the locale and date in numeric format and returns the appropriately formatted date. </p>
<pre><code class="lang-javascript"><span class="hljs-comment">// src/lib/dateUtils.js</span>
<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">formatDate</span>(<span class="hljs-params">date, locale</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Intl</span>.DateTimeFormat(locale, {
    <span class="hljs-attr">year</span>: <span class="hljs-string">'numeric'</span>,
    <span class="hljs-attr">month</span>: <span class="hljs-string">'long'</span>,
    <span class="hljs-attr">day</span>: <span class="hljs-string">'numeric'</span>
  }).format(date);
}
</code></pre>
<p>You can now use this function in your Svelte app to display the dates correctly for each locale:</p>
<pre><code class="lang-javascript">&lt;!-- src/lib/DateDisplay.svelte --&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { formatDate } <span class="hljs-keyword">from</span> <span class="hljs-string">'./lib/dateUtils'</span>;
  <span class="hljs-keyword">let</span> locale = <span class="hljs-string">'en'</span>;
  <span class="hljs-keyword">let</span> today = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>();
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Today's date: {formatDate(today, locale)}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
</code></pre>
<p>Once implemented, you’ll see the dates get formatted automatically, like below:</p>
<ul>
<li><p>English (US): "September 23, 2024"</p>
</li>
<li><p>Spanish: "23 de septiembre de 2024"</p>
</li>
<li><p>German: "23. September 2024"</p>
</li>
<li><p>Japanese: "2024年9月23日"</p>
</li>
</ul>
<h3 id="heading-localizing-images">Localizing Images</h3>
<p>Don’t forget that localization isn’t just about translating text—your images need attention, too. Culturally relevant visuals, region-specific content like maps or symbols, and adaptable image formats can make all the difference.</p>
<h4 id="heading-dynamic-image-paths"><strong>Dynamic Image Paths</strong></h4>
<p>Use Svelte's reactivity to dynamically load images based on the current locale. For example, you can store localized image paths in a JSON file or directly in your i18n configuration:</p>
<pre><code class="lang-javascript">{
  <span class="hljs-string">"en"</span>: { <span class="hljs-string">"logo"</span>: <span class="hljs-string">"/images/en/logo.png"</span> },
  <span class="hljs-string">"fr"</span>: { <span class="hljs-string">"logo"</span>: <span class="hljs-string">"/images/fr/logo.png"</span> }
}
</code></pre>
<p>Then, in your Svelte component:</p>
<pre><code class="lang-javascript">&lt;script&gt;
  <span class="hljs-keyword">import</span> { locale } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte-i18n'</span>;
  <span class="hljs-keyword">import</span> translations <span class="hljs-keyword">from</span> <span class="hljs-string">'./translations.json'</span>;

  $: imagePath = translations[$locale].logo;
&lt;/script&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">img</span> <span class="hljs-attr">src</span>=<span class="hljs-string">{imagePath}</span> <span class="hljs-attr">alt</span>=<span class="hljs-string">"Localized logo"</span> /&gt;</span></span>
</code></pre>
<h4 id="heading-integrating-alternative-text-localization"><strong>Integrating Alternative Text Localization</strong></h4>
<p>Ensure your images' alt attributes are also localized. You can achieve this by adding an additional field in your translations:</p>
<pre><code class="lang-javascript">{
  <span class="hljs-string">"en"</span>: { <span class="hljs-string">"logoAlt"</span>: <span class="hljs-string">"Company Logo"</span> },
  <span class="hljs-string">"fr"</span>: { <span class="hljs-string">"logoAlt"</span>: <span class="hljs-string">"Logo de l'entreprise"</span> }
}

Then bind the localized alt text dynamically
</code></pre>
<pre><code class="lang-javascript">
&lt;img src={imagePath} alt={translations[$locale].logoAlt} /&gt;
</code></pre>
<h4 id="heading-switching-svg-content-dynamically"><strong>Switching SVG Content Dynamically</strong></h4>
<p>If you need to localize content within SVGs, such as text or icons or want to <a target="_blank" href="https://www.adobe.com/express/feature/image/convert/svg">convert to SVG</a> format, consider using Svelte's templating for seamless integration.</p>
<pre><code class="lang-javascript">&lt;svg&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">text</span> <span class="hljs-attr">x</span>=<span class="hljs-string">"10"</span> <span class="hljs-attr">y</span>=<span class="hljs-string">"20"</span>&gt;</span>{$t('svgText')}<span class="hljs-tag">&lt;/<span class="hljs-name">text</span>&gt;</span></span>
&lt;/svg&gt;
</code></pre>
<p>This approach ensures your SVGs are directly rendered with localized text.</p>
<h3 id="heading-handling-multiple-forms-of-pluralization">Handling Multiple Forms of Pluralization</h3>
<p>While many languages have two forms of plurals (singular and plural), there are many languages with more than two forms, and some don’t pluralize. For example:</p>
<ul>
<li><p>Arabic has six forms</p>
</li>
<li><p>Japanese doesn't pluralize in the same way</p>
</li>
</ul>
<p>We can easily handle these differences using svelte-i18n's ICU message syntax. I’ve also added an example of how you can handle more than two forms when using Arabic.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// src/locales/en.json</span>
{
  <span class="hljs-string">"items"</span>: {
    <span class="hljs-string">"count"</span>: <span class="hljs-string">"{count, plural, =0 {No items} one {1 item} other {{count} items}}"</span>
  }
}

<span class="hljs-comment">// src/locales/es.json</span>

{
  <span class="hljs-string">"items"</span>: {
    <span class="hljs-string">"count"</span>: <span class="hljs-string">"{count, plural, =0 {Sin elementos} one {1 elemento} other {{count} elementos}}"</span>
  }
}

<span class="hljs-comment">// src/locales/ar.json</span>
{
  <span class="hljs-string">"items"</span>: {
    <span class="hljs-string">"count"</span>: <span class="hljs-string">"{count, plural, =0 {لا عناصر} one {عنصر واحد} two {عنصران} few {# عناصر} many {# عنصر} other {# عنصر}}"</span>,
  }
}
</code></pre>
<p>Now, let's create the pluralization component for our Svelte app where a button increments the count with every click.</p>
<pre><code class="lang-javascript">&lt;!-- src/lib/ItemCounter.svelte --&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> {  } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte-i18n'</span>;
  <span class="hljs-keyword">let</span> count = <span class="hljs-number">0</span>;
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{$('items.count', { count })}<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">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> count++}&gt;Add Item<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">on:click</span>=<span class="hljs-string">{()</span> =&gt;</span> count--} disabled={count === 0}&gt;Remove Item<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>
</code></pre>
<p>With this implemented, your app is fully ready to handle pluralization dynamically (as you’ll notice by clicking on the <strong>Add item</strong> button). </p>
<h3 id="heading-handling-missing-translations">Handling Missing Translations</h3>
<p>Sometimes, translations for certain keys might be missing. This can happen due to oversight, dynamic content, or incomplete translation files. To handle such scenarios gracefully, set up error handling using the <strong>missingKeyHandler</strong> option in <strong>svelte-i18n</strong>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { register, init } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte-i18n'</span>;

register(<span class="hljs-string">'en'</span>, <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./locales/en.json'</span>));
register(<span class="hljs-string">'es'</span>, <span class="hljs-function">() =&gt;</span> <span class="hljs-keyword">import</span>(<span class="hljs-string">'./locales/es.json'</span>));

init({
  <span class="hljs-attr">fallbackLocale</span>: <span class="hljs-string">'en'</span>,
  <span class="hljs-attr">initialLocale</span>: <span class="hljs-string">'en'</span>,
  <span class="hljs-attr">missingKeyHandler</span>: <span class="hljs-function">(<span class="hljs-params">locale, key</span>) =&gt;</span> {
    <span class="hljs-built_in">console</span>.warn(<span class="hljs-string">`Missing translation: <span class="hljs-subst">${key}</span> (<span class="hljs-subst">${locale}</span>)`</span>);
    <span class="hljs-keyword">return</span> key; <span class="hljs-comment">// Display the key itself when translation is missing</span>
  }
});
</code></pre>
<p>This code logs a warning when a translation is missing and displays the key instead of showing nothing.</p>
<h2 id="heading-making-your-app-production-ready">Making Your App Production-Ready</h2>
<p>When preparing your app for real-world users, optimize it for localization by automatically detecting the user’s language. </p>
<p>You can use the browser’s <strong>navigator.language</strong> property to set the initial locale:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">import</span> { init, getLocaleFromNavigator } <span class="hljs-keyword">from</span> <span class="hljs-string">'svelte-i18n'</span>;

init({
  <span class="hljs-attr">fallbackLocale</span>: <span class="hljs-string">'en'</span>,
  <span class="hljs-attr">initialLocale</span>: getLocaleFromNavigator(),
});
</code></pre>
<h2 id="heading-best-practices-for-scaling-your-localization">Best Practices for Scaling Your Localization</h2>
<ul>
<li><p><strong>Organize translations</strong>: Group related translations logically (for example, buttons, menus, notifications) and use consistent naming patterns for keys.</p>
</li>
<li><p><strong>Use a translation management platform:</strong> As your app grows, handling translation files manually starts becoming cumbersome. <a target="_blank" href="https://centus.com/">Translation management platforms</a> are purpose-built to solve this exact issue and help save hours every day, make it easy to collaborate on projects, and keep track of progress.</p>
</li>
<li><p><strong>Thorough testing</strong>: Test your app with real users across all supported languages. You also need to keep in mind the text length changes to avoid issues with layouts, especially with languages like German or Arabic, which can expand text significantly.</p>
</li>
<li><p><strong>Cultural considerations</strong>: Adapt your app for cultural norms, reading directions (for example, RTL for Arabic), and regional preferences (for example, date and currency formats). </p>
</li>
</ul>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>Localization might feel like a big task at first, but it’s totally worth it. It lets you reach more people and makes your app more inclusive.</p>
<p>Svelte and svelte-i18n streamline the process and keep it fun as you build your skills.</p>
<p>To keep it simple, start with the basics, such as adding translations and a language switcher. Advanced features like handling dates, currencies, and pluralization can follow as you gain confidence. </p>
<p>Take your time, test thoroughly, and build an app that feels natural for all the users you serve!</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
