Svelte i18n: A step-by-step guide

In this article, we will take you through a step-by-step guide on how to perform Svelte internationalization or “i18n”. Also known as globalization, internationalization refers to developing an application that quickly enables localization, targeting a locale that has cultural and language variations when compared to the source. Internationalization is often dubbed i18n as the 18 stands for the number of letters between “i” and “n”.

Adapting the content of an application to match the language and cultural requirements of a specific region or a locale is known as localization or l10n. It’s referred to as l10n because there are ten letters in the word “localization” between “l” and “n.” Some believe that localization is merely translating an application to a target language or variant. However, in reality it deals with much more complex issues such as those related to customization of an application. It is also concerned with aspects like numerical data, date and time formats, currency, symbols, the reading direction of text, and much more.

You may also be interested in learning how to translate Vue applications or how to perform localization in Angular.

An introduction to Svelte

Written by Rich Harris, Svelte is a FOSS JS component framework for building fast web applications. Some see this as a radically new approach, different to React or Vue. While the traditional frameworks allow us to write declarative state-driven programs, the browser takes care of all the work around converting them into DOM operations. However, in Svelte, your components are converted into imperative code, and in build time, it updates the DOM. This provides better performance on the client-side. 

Prerequisites for introducing Svelte i18n

These are:

  • Node: >= 11.15.0.
  • Browsers: Chrome 38+, Edge 16+, Firefox 13+, Opera 25+, Safari 8+.

Also, we assume that you have knowledge of the following prior to beginning this tutorial:

  • Basic JavaScript.
  • HTML and CSS.

Before we move on to the localization side of the application, let’s get a basic idea of how things work in Svelte

Components

A web application built with Svelte is composed of one or more components. Written into a .svelte file using HTML, CSS, or JavaScript, these are the building blocks of an application. They are self-contained and can be reused. When working with components, the two most important things to know are props and lifecycle methods.

Props

When there are multiple components in an application, we need to pass data from one component to another; from parent components to child components. Otherwise, you can access particular values only within the same component. Passing data is done by declaring properties or props. You can use the export keyword in Svelte to declare props. 

Lifecycle methods

Each component has a lifecycle. When a component is created, the lifecycle begins, and it ends once the component is destroyed. You can use several functions during the lifecycle of a component like onMount, onDestroy. The onMount function runs when a component is first rendered to the DOM, and the onDestroy function runs code when your component is destroyed. There are other functions such as beforeUpdate, afterUpdate, and tick in the lifecycle of a Svelte component.

Getting Started with Svelte

You can use degit, which is a is a project scaffolding tool, to create a new project in Svelte. Enter the following command in the terminal and it will create a new project called “my-svelte-project” as well as installing all the dependencies required to run Svelte:

npx degit sveltejs/template my-svelte-project

First, navigate to your new project by using cd and providing the relative path to your project:

Next, run an npm install command to install the packages associated with Svelte:

Svelte i18n

Now, you can start your development server by running this command:

npm run dev

This will start your server at localhost:5000, and you will see the following output in your browser:

Svelte i18n

Internationalizing and Localizing your App UI with Svelte i18n

If you are thinking of internationalizing your Svelte application, I’m afraid there are fewer options when it comes to libraries compared to other JS frameworks. We’ll be using Svelte i18n introduced by Christian Kaisermann to internationalize our demo application.

Svelte i18n makes use of reactive tools in the Svelte framework to internationalize your application easily. It uses stores to track the current locale of the application and the dictionary of translation messages, and to format messages. The stores in Svelte (svelte/stores module) export functions to create readable, writable, and derived stores.

Laying foundations

Installing Svelte i18n

Open a terminal window and run the following command if you are using npm for package management:

npm install svelte-i18n

If you are using Yarn for package management, then use this command instead of the above:

yarn add svelte-i18n

You will see the below in your terminal if you have successfully completed the installation:

Svelte i18n

You can also check if the module has been added:

Svelte i18n

Now that you have successfully installed Svelte i18n as a node module in your application, we can begin the localization. Let’s get started on the application.

You can also check the GitHub repository which contains a demo of this article.

Project structure

Consider the folder structure given below. This would be the final folder structure after you have successfully finished this tutorial:

Svelte i18n

So, let’s see sample code snippets of some main files in the application. 

Header.svelte

<script>
  import { _ } from '../../services/i18n';
  import { Link } from "svelte-routing";
  import "../../../node_modules/materialize-css/dist/css/materialize.min.css";
</script>
 
<nav>
  <div class="nav-wrapper">
    <div class="container">
      <Link to="/">
        <span class="brand-logo">Svelte Localization Tutorial</span>
      </Link>
    </div>
      <ul id="nav-mobile" class="right hide-on-med-and-down">
        <li>
          <Link to="/">Home</Link>
        </li>
        <li>
          <Link to="/about">About</Link>
        </li>
        <li>
          <Link to="/contact">Contact Us</Link>
        </li>
      </ul>
    </div>
</nav>

This is how the App.svelte file looks at the start of the demo. Note that this will change with the additions coming in the later sections. 

App.svelte

<script>
    import "../node_modules/materialize-css/dist/css/materialize.css";
 
    import { Router, Route } from "svelte-routing";
    import Header from './components/Layout/Header.svelte';
    import Footer from './components/Layout/Footer.svelte';
    import About from './components/Pages/About.svelte';
    import Contact from './components/Pages/Contact.svelte';
    import FrameworkGrid from './components/Frameworks/FrameworkGrid.svelte';
</script>
 
<style>
    main { padding: 0 1rem; }
</style>
 
<Router>
    <Header />
    <div class="container">
      <Route path="/contact" component={Contact} />
      <Route path="/about" component={About} />
    </div>
</Router>
<main role="main">
  <FrameworkGrid />
</main>
<Footer />

Now that I’ve given you the basic structure of the application, let’s add i18n to it.

We’ll add three locales: English (default), Arabic, and French. Let’s modify the App.svelte file adding the following code to the script:

<script>
  //..
  import {
    dictionary,
    locale
  }
  from 'svelte-i18n';
  dictionary.set({
    en: {
      "home": {
        "topic": "Svelte Localization Tutorial",
        "subtopic": "Internationalization and Localization"
      },
      "header": {
        "home": "Home",
        "contact": "Contact Us",
        "about": "About"
      }
    },
    ar: {
      "home": {
        "topic": "البرنامج التعليمي Svelte Localization",
        "subtopic": "مجموعة أفلام مختارة من الثمنينات"
      },
      "header": {
        "home": "الصفحة الرئيسية",
        "contact": "اتصل",
        "about": "حول"
      }
    },
    fr: {
      "home": {
        "topic": "Tutoriel de localisation Svelte ",
        "subtopic": "Internationalization and Localization"
      },
      "header": {
        "home": "Accueil",
        "contact": "Nous contacter",
        "about": "À propos"
      }
    },
  });
  locale.set('fr');
</script>

The translated messages are stored in the dictionary. Regular Svelte stores are provided by Svelte i18n to set this dictionary and the current locale.

Please note that the dictionary with the messages must be set before setting the active locale. Otherwise, the library will throw out an error. 

The Messages Dictionary

To keep the translated messages, the Svelte i18n library uses a key-value map. Locale codes like en for English, ar for Arabic, and fr for French are used as top-level keys. You can put your translated messages under every locale code.

Now we have to reflect on the changes from the Header.svelte file:

Header.svelte

<script>
import { _ } from '../../services/i18n';
import { Link } from "svelte-routing";
//..
</script>
 
<nav>
<div class="nav-wrapper">
  <div class="container">
    <Link to="/">
      <span class="brand-logo">{$_('home.topic')}</span>
    </Link>
  </div>
    <ul id="nav-mobile" class="right hide-on-med-and-down">
      <li>
        <Link to="/">{$_('header.home')}</Link>
      </li>
      <li>
        <Link to="/about">{$_('header.about')}</Link>
      </li>
      <li>
        <Link to="/contact">{$_('header.contact')}</Link>
      </li>
    </ul>
  </div>
</nav>

The above changes will create the following output:

Notice how Svelte 18n provides us with a store: _() (underscore) to retrieve the relevant data in the currently configured locale. To fetch the data, we have to give the message’s ID in the brackets as given in the above code. 

Also, as mentioned in Svelte i18n documentation, you can replace _() with format(). Effectively, the underscore feature is only an alias of format()

As you can see, the messages are nested in the dictionary given in the App.svelte file, where we use [] to retrieve the deeply nested messages. Both the title and the subtitle are nested under the home key and are retrieved using ('home.topic'). If you cannot retrieve data using that method, please use the square brackets notation like so: ('home')['topic']

Flat naming scheme

It’s not necessary to nest the strings in this way. You can choose to use a flat list of messages as well. See the example given below:

import { dictionary, locale } from 'svelte-i18n';
dictionary.set({
        en: {
       		"topic": "Svelte Localization Tutorial",
       		"subtopic": "Internationalization and Localization",
       		"home": "Home",
       		"contact": "Contact Us",
       		"about": "About"
        },
        ar: {
       		"topic": "البرنامج التعليمي Svelte Localization",
       		"subtopic": "مجموعة أفلام مختارة من الثمنينات",
       		"home": "الصفحة الرئيسية",
       		"contact": "اتصل",
       		"about": "حول"
        },
        fr: {
       		"topic": "Tutoriel de localisation Svelte ",
       		"subtopic": "Internationalization and Localization",
       		"home": "Accueil",
       		"contact": "Nous contacter",
       		"about": "À propos"
        },
    });
locale.set('fr');

The only difference is now that you have not nested the messages, you don’t need to use either the dot notation or the square brackets notation to retrieve the messages. You can use it straightforwardly as: {$_('title')}.

Now we’ll see what the symbol $ stands for. It’s a shortcut notation provided by the Svelte framework. What it does is ask Svelte to subscribe to the _ (underscore) store and then unsubscribe whenever the current component is destroyed. This is how reactivity is achieved in the application. The component is kept reactive to the _ store. If the current locale or the dictionary in the _ store changes, the component (Home.svelte file) will reload or rerender to reflect the modified code. Another reason to use this is to avoid memory leaks.

Refactoring to a Custom i18n Adapter

Yes, we did set up our code for internationalization in the App.svelte file, but is it okay to keep adding content to this?  It is fine, but the file will probably become messy and overloaded with data when the application grows. Maintaining clean code is a good practice. So, let’s move our internationalizing code to a separate directory and a separate file. 

Create a subdirectory in the src directory named services.

Add a new i18n.js file inside it with this code:

import {
  dictionary,
  locale,
  _
} from 'svelte-i18n';

function setupI18n({
  withLocale: _locale
} = {
  withLocale: 'en'
}) {
  dictionary.set({
    en: {
      "home": {
        "topic": "Svelte Localization Tutorial",
        "subtopic": "Internationalization and Localization"
      },
      "header": {
        "home": "Home",
        "contact": "Contact Us",
        "about": "About"
      }
    },
    ar: {
      "home": {
        "topic": "البرنامج التعليمي Svelte Localization",
        "subtopic": "مجموعة أفلام مختارة من الثمنينات"
      },
      "header": {
        "home": "الصفحة الرئيسية",
        "contact": "اتصل",
        "about": "حول"
      }
    },
    fr: {
      "home": {
        "topic": "Tutoriel de localisation Svelte ",
        "subtopic": "Internationalization and Localization"
      },
      "header": {
        "home": "Accueil",
        "contact": "Nous contacter",
        "about": "À propos"
      }
    },
  });
  locale.set(_locale);
}
export {
  _,
  setupI18n
};

This is a wrapper module where our custom i18n logic resides.

Now that we have inserted our code in the function called setupI18n(), let’s modify the App.svelte file accordingly:

<script>
    import { setupI18n } from './services/i18n';
    
    // ...
    setupI18n({ withLocale: 'en' });
</script>

As you can see, the App.svelte page now has a cleaner code. 

Make sure you modify the code in the Header.svelte and other components where you are also using the internationalization.

<script>
import { _ } from '../../services/i18n';
</script>

Instead of directly importing the store from Svelte i18n, we have imported the forwarded store. 

With the above step, we were able to make our code more flexible and generalizable. If you ever feel like switching your internationalization svelte-i18n library with another, this step allows you to do it easily. Also, we can keep adding content to our customized i18n logic in the i18n.js file without making drastic changes to the other files in the application.

Locale Detection with Svelte i18n

The Svelte i18n library provides many ways of detecting the locale of a client through the browser. Below are such utilities as explained in the Svelte i18n documentation.

You have to set the init() function before using the local detection as it initializes the fallback language if the detected language isn’t supported by the application. For instance:

import { init } from 'svelte-i18n';
register('en', () => import('./en.json'))
register('ar', () => import('./ar.json'))
register('fr', () => import('./fr.json'))
 
init({
  // fallback to english if the current locale is not in the dictionary
  fallbackLocale: 'en',
  initialLocale: 'fr',
})

First, register your locale and then call it in the init() function. Also, bear in mind if you have not set the init() function, the application will generate an error that it cannot load without an initial locale being set. Here are some of the utility methods introduced in the Svelte i18n library to detect the locale. 

getLocaleFromHostname

Here, the initial locale is identified using the pattern of the current hostname:

import { init, getLocaleFromHostname } from 'svelte-i18n';
 
register('en', () => import('./en.json'))
 
init({
  fallbackLocale: 'en',
  initialLocale: getLocaleFromHostname(/^(.*?)\./),
})

getLocaleFromPathname

The application detects the initial locale by using the current pathname, for instance:

import { init, getLocaleFromPathname } from 'svelte-i18n'
 
register('en', () => import('./en.json'))
 
init({
  fallbackLocale: 'en',
  initialLocale: getLocaleFromPathname(/^\/(.*?)\//),
})

getLocalefromNavigator

Here, the navigator settings of the browser are used to identify the initial locale:

import { init, getLocaleFromNavigator } from 'svelte-i18n'
 
register('en', () => import('./en.json'))
 
init({
  fallbackLocale: 'en',
  initialLocale: getLocaleFromNavigator(),
})

getLocaleFromHash

This utility method helps to obtain the initial locale using a hash string {key}={value}, like so:

import { init, getLocaleFromHash } from 'svelte-i18n'
 
register('en', () => import('./en.json'))
 
init({
  fallbackLocale: 'en',
  initialLocale: getLocaleFromHash('lang'),
})

Using HTTP to dynamically load translation files

So far, we only have one i18n file containing every locale’s messages. However, as the application grows, it is convenient to have one file per supported locale. This means we will need separate JS files for our three languages: English, Arabic, and French.

Create three separate files under a subdirectory called lang in the public directory, for example:  

Let’s see the content of the three created files, which are en.json, fr.json, and ar.json.

public/lang/en.json

{
   "home": {
       "topic": "Svelte Localization Tutorial",
       "subtopic": "Internationalization and Localization"
   },
   "header": {
       "home": "Home",
       "contact": "Contact Us",
       "about": "About"
   },
   "framework": {
       "info": "Let's learn how to do localization with this JavaScript framework. Follow the tutorial and contact us for any issues. ",
       "languages": "There {n, plural, =0 {are no languages} one {# is one languages} other {# are several languages}} in this tutorial",
       "rtl": "{n, plural, =0 {No languages are} one {# Only one language is} other {# Several languages are}} written from left to right ",
       "released_at": "Released {date}"
   },
   "footer": {
       "line1": "Follow localise articles and learn more about localization.",
       "line2": "Made with Svelte and svelte-i18n"
   }
}

public/lang/fr.json

{
   "home": {
       "topic": "Tutoriel de localisation Svelte ",
       "subtopic": "Internationalization and Localization"
   },
   "header": {
       "home": "Accueil",
       "contact": "Nous contacter",
       "about": "À propos"
   },
   "framework": {
       "info": "Apprenons à faire la localisation avec ce framework JavaScript. Suivez le tutoriel et contactez-nous pour tout problème.",
       "languages": "Won {n, plural, =0 {no awards} one {# award} other {# awards}}",
       "rtl": "Nominated for {n, plural, =0 {no awards} one {# award} other {# awards}}",
       "released_at": "Released {date}"
   },
   "footer": {
       "line1": "Suivez les articles de localisation et apprenez-en plus sur la localisation.",
       "line2": "Fabriqué avec Svelte et svelte-i18n"
   }
}

public/lang/ar.json

{
   "home": {
       "topic": "البرنامج التعليمي Svelte Localization",
       "subtopic": "مجموعة أفلام مختارة من الثمنينات"
   },
   "header": {
       "home": "الصفحة الرئيسية",
       "contact": "اتصل",
       "about": "حول"
   },
   "framework": {
       "info": "دعونا نتعلم كيفية إجراء الترجمة مع إطار عمل JavaScript هذا. اتبع البرنامج التعليمي واتصل بنا لأية مشاكل.",
       "languages": "{n, plural, =0 {لم يحوز على جوائز} one {حاز على جائزة #} two {حاز على جائزتين} few {حاز على # جوائز} other {حاز على # جائزة}}",
       "rtl": "{n, plural, =0 {لم يرشح لجوائز} one {رشح لجائزة #} two {رشح لجائزتان} few {رشح لـ# جوائز} other {رشح لـ# جائزة}}",
       "released_at": "صدر {date}"
   },
   "footer": {
       "line1": "اتبع مقالات الأقلمة وتعرف على المزيد حول الأقلمة ",
       "line2":"مصنوعة من Svelte و svelte-i18n"
   }
}

After adding separate locale files as above, let’s update the i18n.js file as shown below:

import { derived } from 'svelte/store';
import { dictionary, locale, _} from 'svelte-i18n';
 
const MESSAGE_FILE_URL_TEMPLATE = '/lang/{locale}.json';
 
let cachedLocale;
 
function setupI18n({ withLocale: _locale } = { withLocale: 'en' }) {
    const messsagesFileUrl = MESSAGE_FILE_URL_TEMPLATE.replace('{locale}', _locale);
 
    return fetch(messsagesFileUrl)
        .then(response => response.json())
        .then((messages) => {
            dictionary.set({ [_locale]: messages });
 
            cachedLocale = _locale;
 
            locale.set(_locale);
        });
}
 
export { _, locale, setupI18n };

The direction of the locale

Some languages, like Arabic, are written from right to left, contrary to the usual way of writing (left to right). When we are building an application to support Arabic, we should consider the reading direction of the layout as well.

import { derived } from 'svelte/store';
import { dictionary, locale, _ } from 'svelte-i18n';
//..
const dir = derived(locale, $locale => $locale === 'ar' ? 'rtl' : 'ltr');
//..
export { _, dir, setupI18n };

If the current locale is Arabic, the value in the dir store is “rtl”. In all other cases in this example, it is “ltr”. If there is more than one language that needs a change of direction, then you may have to use an array or a map to contain the relevant locales. 

Let’s update the App.svelte file to add the direction change, like so:

<script>
   import { setupI18n,locale, dir } from './services/i18n';
   
   //..
 
   $: { document.dir = $dir; }
</script>

Here’s the output once the locale is switched to Arabic: 

Svelte i18n

Pluralization with Svelte i18n

As you all know and may have come across in other localization tutorials, taking care of plurals is essential when dealing with localization. Let’s see how we achieve this in Svelte localization.

Update the /lang/{locale}.js files to fit pluralization.

For example, lang/en.json:

"framework": {
        "languages": "There {n, plural, =0 {are no languages} one {# is one languages} other {# are several languages}} in this tutorial",
        "rtl": "{n, plural, =0 {No languages are} one {# Only one language is} other {# Several languages are}} written from left to right"
    },

We can see the use of ICU plural messages in svelte-i18n here. The standard ICU syntax for plurals: {key, plural, matches}, is used here. Please check the documentation for FormatJS to learn more about this. Let’s use the newly set plural messages in the component:

Framework.svelte

<p>{$_('framework.languages', { n: 3 })}</p>
<p>{$_('framework.rtl', { n: 1 })}</p>

The use of $_() can be seen in the plurals as in other messages we accessed previously. The additional step here is that we have passed a number to the variable we declared in the ICU format.

Note that different languages have different pluralization rules, which can be found at the Unicode CLDR website.

Date Formatting

Different countries represent dates and times in ways that are specific to their regions. Therefore, we have to consider date and time formats according to the active locale of the application. The Svelte i18n provides an easy way to accomplish this. You only have to use $_.date().

$date(date: Date, options: MessageObject)

You can add two parameters within this $_date() function. The first parameter is a Date object, and the second parameter is to present the date in preset formats like short, medium, or long. 

As mentioned in the official svelte-i18n documentation, this formats a date object into a string according to the format given by the user. Here are some of the available formats in Svelte i18n.

  • short: { month: 'numeric', day: 'numeric', year: '2-digit' }.
  • medium: { month: 'short', day: 'numeric', year: 'numeric' }.
  • long: { month: 'long', day: 'numeric', year: 'numeric' }.
  • full: { weekday: 'long', month: 'long', day: 'numeric', year: 'numeric' }.

Before using the date function, you have to import it into the file, as follows:

import { date } from 'svelte-i18n'
 
<div>{$date(new Date(2020, 3, 24, 23, 45))}</div>
<div>{$date(new Date(2019, 3, 24, 23, 45), { format: 'medium' } )}</div>

It will output the following:

3/24/20

Mar 24, 2019

Time Formatting

Now, let’s see how we can format time according to the application’s active locale. The following function can be used in Svelte i18n to handle time settings within a locale.

$time(number: Date, options: MessageObject)

As with every other function, you have to import it into the script of the relevant file as below: 

import { time } from 'svelte-i18n'

<div>{$time(new Date(2019, 3, 24, 23, 45))}</div>
<div>{$time(new Date(2019, 3, 24, 23, 45), { format: 'medium' } )}</div>

The output of the above code will be:

11:45 PM

11:45:00 PM

What this does is format a date object into a time string, and here are the available options or formats you can use with time: 

  • short: { hour: 'numeric', minute: 'numeric' }.
  • medium: { hour: 'numeric', minute: 'numeric', second: 'numeric' }.
  • long: { hour: 'numeric', minute: 'numeric', second: 'numeric', timeZoneName: 'short' }.
  • full: { hour: 'numeric', minute: 'numeric', second: 'numeric', timeZoneName: 'short' }.

Numbers and currency

Numbers and currency are represented differently in different countries. To handle this, Svelte i18n provides the following function:

$number(number: number, options: MessageObject)

Import it to the file in which you want to use it:

import { number } from 'svelte-i18n'

<div>{$number(100000000)}</div>
<div>{$number(100000000, { locale: 'pt' })}</div>

The above code will print the following output on your screen:

100,000,000

100.000.000

While this formats a number according to the specified locale and format, there are predefined formats in the library, as given below:

  • currency: { style: 'currency' }.
  • percentage: { style: 'percent' }.
  • scientific: { notation: 'scientific' }.
  • engineering: { notation: 'engineering' }.
  • compactLong: { notation: 'compact', compactDisplay: 'long' }.
  • compactShort: { notation: 'compact', compactDisplay: 'short' }.

Creating a locale switcher for Svelte i18n

Now you have basic knowledge of how to handle internationalization with Svelte using svelte-i18n. To simplify things for the application we are building, let’s try to create a locale switcher with which a user can select the language he/she wants to see in the application.

src/components/Controllers/LocaleSwitcher.svelte

<script>
  import {
    createEventDispatcher
  } from 'svelte';
  export let value = 'en';
  const dispatch = createEventDispatcher();

  function switchLocale(event) {
    event.preventDefault();
    dispatch('locale-changed', event.target.value);
  }
</script>
<style>
  .choose-locale {
    display: flex;
    justify-content: center;
  }

  .select {
    margin: 0 1rem 1rem;
  }
</style>
<div class="choose-locale">
  <div class="select"> <select value={value} on:change={switchLocale}>
      <option value="en">English</option>
      <option value="ar">عربي</option>
      <option value="fr">French</option>
    </select> </div>
</div>

Remember how we discussed Svelte components at the beginning of this article? The LocaleSwitcher is also just another simple Svelte component. What this does is wrap an HTML <select> element and expose the set value in it as well as a custom event as "locale-changed". When the user selects his or her desired language from the dropdown menu, the event: locale-changed is fired, and the selected value is given to the subscribers to that event. 

Let’s add the following to our App.svelte file to add the LocaleSwitcher:

<script>
    import LocaleSwitcher from './components/Controllers/LocaleSwitcher.svelte';
</script>
<LocaleSwitcher
        value={$locale}
        on:locale-changed={e => setupI18n({ withLocale: e.detail }) }
/>

Now you can switch and choose the language you want for your content within the page itself: 

Svelte i18n

Simplifying the Translation Process with Lokalise

When we are localizing any application, the most time consuming and difficult process is not building the application but translating the texts. This is where Lokalise can assist you with Svelte translations. You just need to carry out a few basic steps to integrate Lokalise into your environment and you will see how easy and pain free localizing your applications can be.

  1. Enter a free trial to continue.
  2. Next, install the Lokalise CLI. You can use it to create projects, upload, and download translation files.
  3. Go to the “API tokens” section on your personal profile page and generate a read/write token.
  4. Create a new project and set English as the base language.
  5. Go to Settings by clicking on “More” on the project page.
  6. Copy the project ID and the generated token and then run: lokalise2 file upload --token <token> --project-id <project_id> --lang_iso en --file PATH/TO/PROJECT/public/lang/en.json.
  7. The above step should upload English translations to Lokalise. To upload further languages, run the same command for the other JSON files.
  8. Head over to the project overview page. All your translation keys and values will be there. You can modify them as much as you like by editing, deleting, and adding new ones. You can filter the keys, for example, you can find the untranslated ones which is very convenient.
  9. Download the edited translations and run: lokalise2 file download --token <token> --project-id <project_id> --format json --dest PATH/TO/PROJECT/public/lang.

Learn more about how to incorporate Lokalise into your projects here. With its multi-platform and format support, you can not only request translations from professionals but also upload screenshots from which text can be read. So, why wait? Integrate your applications with Lokalise today and see the wonders that await you. 

Conclusion

When the traditional frameworks to which we have become so addicted are forcing all the hard work onto the browser, Svelte follows a different approach. It generates code to manipulate the DOM and hence is referred to more as a compiler than a framework. 

Up to date, the only known library for incorporating internationalization in Svelte is Svelte i18n. It is fairly new, so you may come across some issues while building your application with it. However, the Svelte i18n community promises to keep everything neat and in sync. They are also committed to ease of use. 

It may not be easy to begin with, as stated in the documentation, but with the necessary corrections and error handling, you will be able to achieve i18n with Svelte apps using the Svelte i18n library. Please refer to our code in Github and contact us if there’s anything you would like to clarify.

Related posts

Sign up to our newsletter

Get the latest articles on all things localization and translation management delivered straight to your inbox.

Read also
Localization made easy. Why wait?
The preferred localization tool of 1500+ leading global companies