Internationalization with SvelteKit (Multiple Language Support)

Published: May 12, 2024

Internationalization with SvelteKit (Multiple Language Support)

Background

In order to increase traffic to your website, you might consider adding language support to your website.

For example, below chart shows the # visits per page on my website as of May 12 2024.

Most Visited Pages

Although most of the visits happened to the English pages (because overall landing page is in English), there is significant amount of visits made to the Turkish and Japanese versions. You definitely wouldn't want to miss on these potential visits to your websites.

Moreover, considering that ChatGPT translations are pretty good nowadays, the effort needed for translating the content is also not as high as it used to be. While ChatGPT translations are usualy not perfect, it provides a great working board when translating the content.

How to make your website international with SvelteKit?

Although I haven't done any research on the topic, let me explain my strategy for enabling 3 languages on my website with as much streamlining as possible. The approach is 3 pronged:

1. Routing strategy

My website is structured as www.danyelkoca.com/<language>/<something>

. Below are some actual routes:

This way of routing can be achieved by this folder structure in your routes folder under the src folder:

Folder Structure

Since my website has 3 languages, there are 3 subfolders within the src folder.

  • en
  • jp
  • tr

Each subfolder has almost identical contents, but this is not required. E.g. if you have products page only in English, having products subfolder only under the en folder would make sense.

2. State management strategy

When routing is done, we need to track the language of user's choice. Because in most cases, you won't have separate page for each language. For example:

let language = "en"; // jp or tr is possible
let greeting = language == "en" ? "Hello" : language == "jp" : "こんにちは"  : "Selam";

Of course, we won't declare a variable in each page, but will be using a writable store in SvelteKit.

 // stores/main.js
import { writable } from 'svelte/store';
export const language = writable('en');

This store variable is imported as needed in our components and used as below:

<script>
	import { language } from '$stores/main'
	let title = $language == "en" ? "About" : $language == "jp" : "私について" : "Hakkimda";
</script>

<svelte:head>
	<title>{title}</title>
</svelte:head>

3. Component strategy

Now, how do we serve content per language if we have different route for each language? What I mean is, we have different page.svelte per page and language.

  • en/contact/page.svelte
  • jp/contact/page.svelte
  • tr/contact/page.svelte

If the content we are serving in our pages are similar, we will have 1 component, and make adjustments based on the language using conditionals.

So each page.svelte in the above example will refer to the same Contact component:

<script>
	import Contact from 'components/Contact.svelte';
</script>

<Contact />

And within the Contact component, we will create content dynamically based on the stored language variable.

 // components/Contact.svelte
<script>
	import { language } from '$stores/main'
</script>

<h1>
		{$language == 'en' ? 'Contact Me' : $language == 'jp' ? '問い合わせ' : 'İletişim'}
</h1>

However, some of your pages will have very different content depending on the language, so creating the content based on conditionals in a large page will be a nightmare (For example, a blog post). For those, I recommend creating a separate component per language.

4. Other considerations: Updating the store

One last thing you need to consider is that, you need to keep track of the language variable in your store. Your website will have a language button that will work like this:

<div>
	<button on:click={() => language.set('en')}>English</button>
	<button on:click={() => language.set('jp')}>Japanese</button>
	<button on:click={() => language.set('tr')}>Turkish</button>
</div>

This is easy to manage. However, your stored value for language will have an initial value such as en. When user visits directly a Japanese or Turkish page, you still need to update the language variable before the page is even displayed, so that you show the right content to the user.

For this we use page.js in SvelteKit that is usually used to load data. This page runs before page.svelte is loaded and it is the perfect place to do any state changes:

// routes/jp/{something}/page.svelte
import { language } from '$stores/main';
language.set('jp');

Note that you need to do this for Turkish and English routes as well. For English, you may think that this is not needed as the default store value is English. But there might be a case where user changes the language to Japanese, and visits an English site, in this case the language would be stuck in Japanese. We'd like to prevent such instances.

Supporting multiple languages in SvelteKit

Conclusion

In this blogpost, I have summarized the strategies I'm employing to make it easy to deploy my site in 3 languages. Managing a website in multiple languages can be messy, but we can use the SvelteKit functions to give a smooth experience to the user, and reduce the workload of the engineer.

Do you have a better approach? Let me know.

In the meantime, happy hacking!

Leave comment

Comments

Check out other blog posts

Create A Simple and Dynamic Tooltip With Svelte and JavaScript

2024/06/19

Create A Simple and Dynamic Tooltip With Svelte and JavaScript

JavaScriptSvelteSimpleDynamicTooltipFront-end
Create an Interactive Map of Tokyo with JavaScript

2024/06/17

Create an Interactive Map of Tokyo with JavaScript

SvelteSVGJavaScriptTailwindInteractive MapTokyoJapanTokyo Metropolitan Area23 Wards
How to Easily Fix Japanese Character Issue in Matplotlib

2024/06/14

How to Easily Fix Japanese Character Issue in Matplotlib

MatplotlibGraphChartPythonJapanese charactersIssueBug
Book Review | Talking to Strangers: What We Should Know about the People We Don't Know by Malcolm Gladwell

2024/06/13

Book Review | Talking to Strangers: What We Should Know about the People We Don't Know by Malcolm Gladwell

Book ReviewTalking to StrangersWhat We Should Know about the People We Don't KnowMalcolm Gladwell
Most Commonly Used 3,000 Kanjis in Japanese

2024/06/07

Most Commonly Used 3,000 Kanjis in Japanese

Most CommonKanji3000ListUsage FrequencyJapaneseJLPTLanguageStudyingWordsKanji ImportanceWord Prevalence
Replace With Regex Using VSCode

2024/06/07

Replace With Regex Using VSCode

VSCodeRegexFindReplaceConditional Replace
Do Not Use Readable Store in Svelte

2024/06/06

Do Not Use Readable Store in Svelte

SvelteReadableWritableState ManagementStoreSpeedMemoryFile Size
Increase Website Load Speed by Compressing Data with Gzip and Pako

2024/06/05

Increase Website Load Speed by Compressing Data with Gzip and Pako

GzipCompressionPakoWebsite Load SpeedSvelteKit
Find the Word the Mouse is Pointing to on a Webpage with JavaScript

2024/05/31

Find the Word the Mouse is Pointing to on a Webpage with JavaScript

JavascriptMousePointerHoverWeb Development
Create an Interactive Map with Svelte using SVG

2024/05/29

Create an Interactive Map with Svelte using SVG

SvelteSVGInteractive MapFront-end
Book Review | Originals: How Non-Conformists Move the World by Adam Grant & Sheryl Sandberg

2024/05/28

Book Review | Originals: How Non-Conformists Move the World by Adam Grant & Sheryl Sandberg

Book ReviewOriginalsAdam Grant & Sheryl SandbergHow Non-Conformists Move the World
How to Algorithmically Solve Sudoku Using Javascript

2024/05/27

How to Algorithmically Solve Sudoku Using Javascript

Solve SudokuAlgorithmJavaScriptProgramming
How I Increased Traffic to my Website by 10x in a Month

2024/05/26

How I Increased Traffic to my Website by 10x in a Month

Increase Website TrafficClicksImpressionsGoogle Search Console
Life is Like Cycling

2024/05/24

Life is Like Cycling

CyclingLifePhilosophySuccess
Generate a Complete Sudoku Grid with Backtracking Algorithm in JavaScript

2024/05/19

Generate a Complete Sudoku Grid with Backtracking Algorithm in JavaScript

SudokuComplete GridBacktracking AlgorithmJavaScript
Why Tailwind is Amazing and How It Makes Web Dev a Breeze

2024/05/16

Why Tailwind is Amazing and How It Makes Web Dev a Breeze

TailwindAmazingFront-endWeb Development
Generate Sitemap Automatically with Git Hooks Using Python

2024/05/15

Generate Sitemap Automatically with Git Hooks Using Python

Git HooksPythonSitemapSvelteKit
Book Review | Range: Why Generalists Triumph in a Specialized World by David Epstein

2024/05/14

Book Review | Range: Why Generalists Triumph in a Specialized World by David Epstein

Book ReviewRangeDavid EpsteinWhy Generalists Triumph in a Specialized World
What is Svelte and SvelteKit?

2024/05/13

What is Svelte and SvelteKit?

SvelteSvelteKitFront-endVite
Reduce Svelte Deploy Time With Caching

2024/05/11

Reduce Svelte Deploy Time With Caching

SvelteEnhanced ImageCachingDeploy Time
Lazy Load Content With Svelte and Intersection Oberver

2024/05/10

Lazy Load Content With Svelte and Intersection Oberver

Lazy LoadingWebsite Speed OptimizationSvelteIntersection Observer
Find the Optimal Stock Portfolio with a Genetic Algorithm

2024/05/10

Find the Optimal Stock Portfolio with a Genetic Algorithm

Stock marketPortfolio OptimizationGenetic AlgorithmPython
Convert ShapeFile To SVG With Python

2024/05/09

Convert ShapeFile To SVG With Python

ShapeFileSVGPythonGeoJSON
Reactivity In Svelte: Variables, Binding, and Key Function

2024/05/08

Reactivity In Svelte: Variables, Binding, and Key Function

SvelteReactivityBindingKey Function
Book Review | The Art Of War by Sun Tzu

2024/05/07

Book Review | The Art Of War by Sun Tzu

Book ReviewThe Art Of WarSun TzuThomas Cleary
Specialists Are Dead. Long Live Generalists!

2024/05/06

Specialists Are Dead. Long Live Generalists!

SpecialistGeneralistParadigm ShiftSoftware Engineering
Analyze Voter Behavior in Turkish Elections with Python

2024/05/03

Analyze Voter Behavior in Turkish Elections with Python

TurkeyAge Analysis2018 ElectionsVoter Behavior
Create Turkish Voter Profile Database With Web Scraping

2024/05/01

Create Turkish Voter Profile Database With Web Scraping

PythonSeleniumWeb ScrapingTurkish Elections
Make Infinite Scroll With Svelte and Tailwind

2024/04/30

Make Infinite Scroll With Svelte and Tailwind

SvelteTailwindInfinite ScrollFront-end
How I Reached Japanese Proficiency In Under A Year

2024/04/29

How I Reached Japanese Proficiency In Under A Year

JapaneseProficiencyJLPTBusiness
Use-ready Website Template With Svelte and Tailwind

2024/04/25

Use-ready Website Template With Svelte and Tailwind

Website TemplateFront-endSvelteTailwind
Lazy Engineers Make Lousy Products

2024/01/29

Lazy Engineers Make Lousy Products

Lazy engineerLousy productStarbucksSBI
On Greatness

2024/01/28

On Greatness

GreatnessMeaning of lifeSatisfactory lifePurpose
Converting PDF to PNG on a MacBook

2024/01/28

Converting PDF to PNG on a MacBook

PDFPNGMacBookAutomator
Recapping 2023: Compilation of 24 books read

2023/12/31

Recapping 2023: Compilation of 24 books read

BooksReading2023Reflections
Create a Photo Collage with Python PIL

2023/12/30

Create a Photo Collage with Python PIL

PythonPILImage ProcessingCollage
Detect Device & Browser of Visitors to Your Website

2024/01/09

Detect Device & Browser of Visitors to Your Website

JavascriptDevice DetectionBrowser DetectionWebsite Analytics
Anatomy of a ChatGPT Response

2024/01/19

Anatomy of a ChatGPT Response

ChatGPTLarge Language ModelMachine LearningGenerative AI