🌐 Added i18next
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
import i18next from 'i18next';
|
||||
import translations from './translations';
|
||||
import en from './locales/en.json';
|
||||
|
||||
import type { i18n, Resource } from 'i18next';
|
||||
|
||||
const INITIAL_LANGUAGE = 'en';
|
||||
|
||||
export class I18nService {
|
||||
// expose i18next
|
||||
i18n: i18n;
|
||||
constructor() {
|
||||
this.i18n = i18next;
|
||||
this.initialize();
|
||||
this.changeLanguage(INITIAL_LANGUAGE);
|
||||
}
|
||||
|
||||
// Our translation function
|
||||
t(key: string, replacements?: Record<string, unknown>): string {
|
||||
return this.i18n.t(key, replacements);
|
||||
}
|
||||
|
||||
// Initializing i18n
|
||||
initialize() {
|
||||
this.i18n.init({
|
||||
lng: INITIAL_LANGUAGE,
|
||||
fallbackLng: 'en',
|
||||
debug: false,
|
||||
defaultNS: 'translation',
|
||||
fallbackNS: 'common',
|
||||
resources: translations as Resource,
|
||||
interpolation: {
|
||||
escapeValue: false
|
||||
},
|
||||
detection: {
|
||||
order: ['querystring', 'navigator'],
|
||||
lookupQuerystring: 'lng'
|
||||
}
|
||||
});
|
||||
this.i18n.addResourceBundle('en', 'translation', en);
|
||||
}
|
||||
|
||||
changeLanguage(language: string) {
|
||||
this.i18n.changeLanguage(language);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import { I18nService } from './i18n-service';
|
||||
import { I18NextTranslationService } from './translation-service';
|
||||
import type { TType } from './translation-service';
|
||||
import type { Readable, Writable } from 'svelte/store';
|
||||
import { getContext, setContext } from 'svelte';
|
||||
|
||||
export const initLocalizationContext = () => {
|
||||
// Initialize our services
|
||||
const i18n = new I18nService();
|
||||
const tranlator = new I18NextTranslationService(i18n);
|
||||
|
||||
// Setting the Svelte context
|
||||
setLocalization({
|
||||
t: tranlator.translate,
|
||||
currentLanguage: tranlator.locale
|
||||
});
|
||||
|
||||
return {
|
||||
i18n
|
||||
};
|
||||
};
|
||||
const CONTEXT_KEY = 't';
|
||||
|
||||
export type I18nContext = {
|
||||
t: Readable<TType>;
|
||||
currentLanguage: Writable<string>;
|
||||
};
|
||||
|
||||
export const setLocalization = (context: I18nContext) => {
|
||||
return setContext<I18nContext>(CONTEXT_KEY, context);
|
||||
};
|
||||
|
||||
// To make retrieving the t function easier.
|
||||
export const getLocalization = () => {
|
||||
return getContext<I18nContext>(CONTEXT_KEY);
|
||||
};
|
||||
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"index_page": {
|
||||
"slogan": "The open-source quiz-platform!",
|
||||
"meta": {
|
||||
"description": "ClassQuiz is a quiz app like KAHOOT! for students, which is open source and free to use",
|
||||
"title": "Home"
|
||||
},
|
||||
"stats": "Stats",
|
||||
"features": "Features",
|
||||
"features_description": {
|
||||
"1": "ClassQuiz is a quiz-platform that allows you to create and manage quizzes.",
|
||||
"2": "The main feature is a KAHOOT!-import function that allows you to import quizzes from KAHOOT!-quizzes."
|
||||
}
|
||||
},
|
||||
"overview_page": {
|
||||
"create": "Create",
|
||||
"import": "Import",
|
||||
"logout": "Logout",
|
||||
"title": "Title",
|
||||
"created_at": "Created at",
|
||||
"question_count": "Question count",
|
||||
"play": "Play",
|
||||
"edit": "Edit",
|
||||
"delete": "Delete",
|
||||
"public": "Public",
|
||||
"start": "Start"
|
||||
},
|
||||
"edit_page": {
|
||||
"save": "Save",
|
||||
"success_update_title": "Successfully updated quiz!",
|
||||
"success_update_body": "Updated the quiz successfully!",
|
||||
"close": "Close"
|
||||
},
|
||||
"create_page": {
|
||||
"success": {
|
||||
"title": "Successfully created quiz!",
|
||||
"body": "Created the quiz successfully!"
|
||||
},
|
||||
"close": "Close"
|
||||
},
|
||||
"register_page": {
|
||||
"greeting": "Nice to meet you!",
|
||||
"create_account": "Create account",
|
||||
"email": "Email",
|
||||
"username": "Username",
|
||||
"password": "Password",
|
||||
"forgot_password?": "Forgot password?",
|
||||
"register": "Register",
|
||||
"already_have_account?": "Already have an account?",
|
||||
"login": "Login"
|
||||
},
|
||||
"login_page": {
|
||||
"welcome_back": "Welcome back!",
|
||||
"login_or_create_account": "Login or create an account",
|
||||
"already_have_account": "Don't have an account?",
|
||||
"modal": {
|
||||
"success": {
|
||||
"success_check_mail": "Login Succeded! Check your mailbox!",
|
||||
"success": "Login Succeded!",
|
||||
"description": {
|
||||
"success_check_mail": "Please check your mailbox, since you should have received a mail, with a link you can click to login.",
|
||||
"success": "You've successfully logged in!"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"wrong_creds": "Wrong email or password!",
|
||||
"unexpected": "Unexpected error!",
|
||||
"description": {
|
||||
"wrong_creds": "Please make sure that your password and your email are correct!",
|
||||
"unexpected": "There was the good old unexpected error!"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import type { I18nService } from './i18n-service';
|
||||
import { derived, writable } from 'svelte/store';
|
||||
import type { Readable, Writable } from 'svelte/store';
|
||||
|
||||
export type TType = (text: string, replacements?: Record<string, unknown>) => string;
|
||||
|
||||
export interface TranslationService {
|
||||
locale: Writable<string>;
|
||||
translate: Readable<TType>;
|
||||
}
|
||||
|
||||
export class I18NextTranslationService implements TranslationService {
|
||||
public locale: Writable<string>;
|
||||
public translate: Readable<TType>;
|
||||
|
||||
constructor(i18n: I18nService) {
|
||||
i18n.initialize();
|
||||
this.locale = this.createLocale(i18n);
|
||||
this.translate = this.createTranslate(i18n);
|
||||
}
|
||||
|
||||
// Locale initialization.
|
||||
// 1. Create a writable store
|
||||
// 2. Create a new set function that changes the i18n locale.
|
||||
// 3. Create a new update function that changes the i18n locale.
|
||||
// 4. Return modified writable.
|
||||
private createLocale(i18n: I18nService) {
|
||||
const { subscribe, set, update } = writable<string>(i18n.i18n.language);
|
||||
|
||||
const setLocale = (newLocale: string) => {
|
||||
i18n.changeLanguage(newLocale);
|
||||
set(newLocale);
|
||||
};
|
||||
|
||||
const updateLocale = (updater: (value: string) => string) => {
|
||||
update((currentValue) => {
|
||||
const nextLocale = updater(currentValue);
|
||||
i18n.changeLanguage(nextLocale);
|
||||
return nextLocale;
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
update: updateLocale,
|
||||
set: setLocale
|
||||
};
|
||||
}
|
||||
|
||||
// Create a translate function.
|
||||
// It is derived from the "locale" writable.
|
||||
// This means it will be updated every time the locale changes.
|
||||
private createTranslate(i18n: I18nService) {
|
||||
return derived([this.locale], () => {
|
||||
return (key: string, replacements?: Record<string, unknown>) =>
|
||||
i18n.t(key, replacements);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export default {
|
||||
en: {
|
||||
common: {
|
||||
'ClassQuiz is a quiz app like KAHOOT! for students, which is open source and free to use.':
|
||||
'ClassQuiz is a quiz app like KAHOOT! for students, which is open source and free to use.',
|
||||
'The open-source quiz-platform!': 'The open-source quiz-platform!'
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user