Skip to content

Commit

Permalink
feat: init i18n
Browse files Browse the repository at this point in the history
  • Loading branch information
lemueldls committed Jun 16, 2023
1 parent 0dc3438 commit 5e76781
Show file tree
Hide file tree
Showing 9 changed files with 251 additions and 51 deletions.
31 changes: 19 additions & 12 deletions packages/client/astro.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@ import { fileURLToPath } from 'node:url';

import { description, name } from '../../package.json';

import { locales, defaultLocale, dir, t, type Locale } from '@kaetram/common/locales';
import { defineConfig } from 'astro/config';
import config, { exposedConfig } from '@kaetram/common/config';
import partytown from '@astrojs/partytown';
import webmanifest from 'astro-webmanifest';
import { i18n } from 'astro-i18n-aut';
import sitemap from '@astrojs/sitemap';
import robotsTxt from 'astro-robots-txt';
import partytown from '@astrojs/partytown';
import critters from 'astro-critters';
import compress from 'astro-compress';
import webmanifest from 'astro-webmanifest';
import compressor from 'astro-compressor';
import glsl from 'vite-plugin-glsl';
import { VitePWA as pwa } from 'vite-plugin-pwa';
Expand Down Expand Up @@ -72,8 +74,8 @@ function getImageSize(image: string) {
export default defineConfig({
srcDir: './',
site: 'https://kaetram.com',
trailingSlash: 'always',
integrations: [
partytown({ config: { debug: false } }),
webmanifest({
icon: 'public/icon.png',
name: config.name,
Expand All @@ -86,20 +88,25 @@ export default defineConfig({
background_color: '#000000',
display: 'fullscreen',
orientation: 'landscape-primary',
locales: {
ro: { name: 'Kaetram', lang: 'ro-RO' }
},
locales: Object.fromEntries(
Object.entries(locales).map(([locale, lang]) => [
locale,
{
lang,
dir: dir(locale as Locale),
name: t('game.name', { lng: locale }),
description: t('game.description', { lng: locale })
}
])
),
config: {
insertAppleTouchLinks: true,
iconPurpose: ['any', 'maskable']
}
}),
sitemap({
i18n: {
defaultLocale: 'en',
locales: { en: 'en-US', ro: 'ro-RO' }
}
}),
partytown({ config: { debug: false } }),
i18n({ locales, defaultLocale }),
sitemap({ i18n: { locales, defaultLocale } }),
robotsTxt({ host: true }),
critters({ logger: 2 }),
compress({ logger: 1 }),
Expand Down
1 change: 1 addition & 0 deletions packages/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"astro-compress": "^1.1.47",
"astro-compressor": "^0.4.0",
"astro-critters": "^1.1.38",
"astro-i18n-aut": "^0.0.13",
"astro-robots-txt": "^0.5.0",
"astro-seo-schema": "^2.0.0",
"astro-webmanifest": "^0.6.0",
Expand Down
17 changes: 17 additions & 0 deletions packages/common/locales/en/store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export default {
WARNING_DUPLICATE: 'Duplicate {{item}} key found in store: ',
INVALID_STORE: 'Tried to parse a non-existent store.',
INVALID_STORE_REFRESH: 'Tried to refresh invalid store: ',
INVALID_ITEM_SELECTION: 'Invalid item selection.',
PURCHASE_INVALID_STORE: 'tried purchasing an item that does not exist store: ',
SELL_INVALID_ITEM: 'tried selling an invalid item.',
ITEM_OUT_OF_STOCK: 'This item is currently out of stock.',
NOT_ENOUGH_CURRENCY: 'You do not have enough currency to buy this item.',
NOT_ENOUGH_SPACE: 'You do not have enough space in your inventory.',
CANNOT_SELL_ITEM: 'You cannot sell this item.',
ACTION_STORE_NOT_OPEN: 'Tried to perform an action on a store that is not open.',
CHEATER: 'You have been flagged for cheating. You cannot purchase anything.',
RESTRICTED_STORE: 'This store does not accept any items.',
INVALID_ITEM_COUNT: 'You have entered an invalid amount of items.',
HOLLOW_ADMIN: 'As an admin you cannot interact with the economy.'
} as const;
7 changes: 7 additions & 0 deletions packages/common/locales/en/translation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default {
game: {
name: 'Kaetram',
description:
"Kaetram is an open-source game-engine created to aid those interested in entering the game development realm. The original idea is based on Little Workshop's demo game - BrowserQuest. The assets have remained the same, but the code itself has been completely wiped and redone from the ground up."
}
} as const;
29 changes: 29 additions & 0 deletions packages/common/locales/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as i18next from 'i18next';
import i18nextBackend from 'i18next-fs-backend';

import type { NsInter } from './ns';

export let locales = { en: 'en-US', ro: 'ro-RO' };
export let defaultLocale = 'en';

export type Locale = keyof typeof locales;

await i18next.use(i18nextBackend).init({
lng: defaultLocale,
fallbackLng: defaultLocale,
preload: Object.keys(locales),
ns: ['translation'],
defaultNS: 'translation',
backend: { loadPath: '{{lng}}/{{ns}}' }
});

export let t = <
K extends keyof NsInter[N],
O extends { ns?: keyof NsInter },
N extends keyof NsInter = O extends { ns: infer N } ? N : 'translation'
>(
key: K,
options?: i18next.TOptions<O & NsInter[N][K]>
) => i18next.t(key as string, options);

export let dir = (locale: Locale) => i18next.dir(locale);
52 changes: 52 additions & 0 deletions packages/common/locales/ns.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import type Translation from './en/translation';
import type Store from './en/store';
import type { TypeOptions } from 'i18next';

type DotValue<T extends string> = T extends `${infer L}.${infer R}`
? { [K in L]: DotValue<R> }
: { [K in T]: string };

type Prefix = TypeOptions['interpolationPrefix'];
type Suffix = TypeOptions['interpolationSuffix'];
type Interpolation<T> = T extends `${string}${Prefix}${infer I}${Suffix}${infer N}`
? DotValue<I> & Interpolation<N>
: unknown;

type TraverseInterpolation<T> = T extends string
? Interpolation<T>
: T extends object
? { [K in keyof T]: TraverseInterpolation<T[K]> }
: never;

type UnionToIntersection<T> = (T extends unknown ? (_: T) => unknown : never) extends (
_: infer R
) => unknown
? R
: never;

type DotFlatten<T> = T extends object
? UnionToIntersection<
{
[K in keyof T]: T[K] extends object
? DotFlatten<
{
[L in keyof T[K]]: {
[M in `${K & string}.${L & string}`]: DotFlatten<T[K][L]>;
};
}[keyof T[K]]
>
: T;
}[keyof T]
>
: T;

export interface Namespace {
translation: typeof Translation;
store: typeof Store;
}

export type NsInter = {
[K in keyof Namespace]: TraverseInterpolation<DotFlatten<Namespace[K]>>;
};

export type { TOptions } from 'i18next';
Empty file.
2 changes: 2 additions & 0 deletions packages/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
"discord.js": "^14.3.0",
"dotenv-extended": "^2.9.0",
"dotenv-parse-variables": "^2.0.0",
"i18next": "^23.0.2",
"i18next-fs-backend": "^2.1.5",
"ipaddr.js": "^2.0.1"
}
}
Loading

0 comments on commit 5e76781

Please sign in to comment.