Experiment with custom i18n content management in SvelteKit
# install modules
npm i
# generate local db instance
npx prisma generate
# launch application locally
npm run dev
This experiment provides a minimally viable proof-of-concept for a custom Xyvid i18n solution, with user accessible content management.
The primary benefit of this approach over other compatible i18n tools is that the localized content is not stored in a flat JSON file, and is maintained through a user interface. This allows content to be created and updated by non-technical team members.
This approach also creates a more streamlined and tailored developer experience compared to some more complex options that attempt to serve many needs at once.
The overarching purpose of this experiment is to help determine whether or not those value propositions outweigh the benefits of existing solutions.
Probably the most obvious existing solution would be svelte-i18n, which follows a pattern similar to leading react and vue libraries. This relies on flat JSON files, so we would have to either maintain them manually or create a tool to generate them from data and publish them to the UI environment. A nice side effect with this package is support from the i18n-ally VS Code plugin.
Another interesting option would be using a headless CMS with i18n support, like Strapi. On the surface, it looks some extra technical debt and learning curve in addition to the tool itself. It does however provide a nice user interface for maintaining content, and supports proper l10n (including images, currency, etc).
The content management tools can be accessed by clicking the i18n button in the top right after launching the application.
The user interface is limited in it's current form, but you are able to create new locales and add/edit text content for a given locale (language).
<h2 class="font-bold">
{_('welcome')}
</h2>
<button>{_('button_submit')}</button>
<LocalText slug="welcome" />
An alternative to the shorthand _ function. This allows for more fine-grain logic when dealing with falling back for missing content, as well as more explicit formatting like setting the language direction attribute directly on a given text element.
Not implemented.
While avoiding language content in images is the best practice, it may happen. There could also be other use cases like localized logos or banner graphics. This component would be a simple mechanism to handle such situations, by providing a simple wrapper to an image tag that uses a localized image URL if available.
<LocalImage image_slug="pwc_event_banner" />
Core functionality for this feature.
This is the primary endpoint for this library. Returns the localized text content for a given slug, or default content as a fallback. The _ underscore function name serves as a shorthand when writing templates with localized content, yielding more readable code. This also follows existing conventions.
Returns localized text for a given slug, or null if not found.
Ignores locale and returns default (en-us) text for a given slug.
Not implemented.
Formats and returns a given number according to localized customs.
Formats a given UTC Date object into localized standards and timezone and returns as a string.
Formats the time of a given UTC Date object into localized standards and returns as a string.
This experiment uses Prisma ORM and a SQLite file based database, but the functionality would remain effectively the same for any relational DB setup.
model Locale {
id Int @id @default(autoincrement())
code String @unique
dir String @default("ltr")
title String
native_title String
LocalText LocalText[]
}
model LocalText {
id Int @id @default(autoincrement())
locale Locale @relation(fields: [localeId], references: [id])
slug String
content String
localeId Int
}
model LocalImage {
id Int @id @default(autoincrement())
locale Int
slug String
content String
}