diff --git a/.gitignore b/.gitignore
index e9a53bf..2d53da6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,4 @@
node_modules/**/*
packages/ioc/node_modules/*
packages/poster/dts/discord.d.ts
+packages/**/node_modules
diff --git a/packages/builder/package.json b/packages/builder/package.json
index 8d4cda2..c7fed0e 100644
--- a/packages/builder/package.json
+++ b/packages/builder/package.json
@@ -18,8 +18,7 @@
"discord-api-types": "latest"
},
"devDependencies": {
- "@types/node": "^20.1.0",
- "typescript": "^5.0.4"
+ "@types/node": "^20.1.0"
},
"keywords": [],
"author": "",
diff --git a/packages/localizer/.gitignore b/packages/localizer/.gitignore
new file mode 100644
index 0000000..3be4a7b
--- /dev/null
+++ b/packages/localizer/.gitignore
@@ -0,0 +1,2 @@
+dist/
+*.tgz
diff --git a/packages/localizer/index.mdx b/packages/localizer/index.mdx
new file mode 100644
index 0000000..eda90fa
--- /dev/null
+++ b/packages/localizer/index.mdx
@@ -0,0 +1,75 @@
+---
+title: Localizer
+description: Translate your bot for the world
+sidebar:
+ order: 1
+---
+
+
+# @sern/localizer
+
+A localization module for managing translations and providing localized content in your application.
+
+## Installation
+
+```
+npm i @sern/localizer
+```
+
+## Usage
+
+**Initializing the Localizer**
+```ts
+import { makeDependencies } from '@sern/handler';
+import { Localization } from '@sern/localizer';
+
+await makeDependencies(({ add }) => {
+ add('localizer', Localization());
+});
+```
+This localizer is **FILE BASED**.
+Create the directory `assets/locals`. Each json file in here must be named after the `locale`
+
+import { Tabs, TabItem } from "@astrojs/starlight/components";
+
+
+
+ ```json title=~/assets/locals/es.json
+ {
+ "salute": {
+ "hello": "hola"
+ }
+ }
+ ```
+
+
+ ```json title=~/assets/locals/en-US.json
+ {
+ "salute": {
+ "hello": "hello"
+ }
+ }
+ ```
+
+
+
+
+
+**Accessing translations**
+- If you are in a command execute callback, use `deps` from SDT.
+```ts
+execute : (ctx, { deps }) => {
+ //the localizer object from makeDependencies
+ deps.localizer
+ // Returns the Spanish translation for 'salute.hello'
+ deps.localizer.translate("salute.hello", "es");
+}
+```
+
+
+```ts
+import { local } from '@sern/localizer';
+
+// Returns the Spanish translation for 'salute.hello'
+const greeting = local('salute.hello', 'es');
+```
diff --git a/packages/localizer/index.ts b/packages/localizer/index.ts
new file mode 100644
index 0000000..a926c7d
--- /dev/null
+++ b/packages/localizer/index.ts
@@ -0,0 +1,145 @@
+import { type Init, Service, CommandInitPlugin, CommandType, controller } from '@sern/handler'
+import { Localization as LocalsProvider } from 'shrimple-locales'
+import fs from 'node:fs/promises'
+import { existsSync } from 'node:fs'
+import { join, resolve } from 'node:path';
+import assert from 'node:assert';
+import { dfsApplyLocalization } from './internal'
+
+
+/**
+ * @since 3.4.0
+ * @internal
+ */
+class ShrimpleLocalizer implements Init {
+ private __localization!: LocalsProvider;
+ private currentLocale: string = "en";
+
+ translationsFor(path: string): Record {
+ return this.__localization.localizationFor(path);
+ }
+
+ translate(text: string, local?: string): string {
+ return this.__localization.get(text, local);
+ }
+
+ setCurrentLocale(local: string): void {
+ this.__localization.changeLanguage(local);
+ }
+
+ async init() {
+ const map = await this.readLocalizationDirectory();
+ this.__localization = new LocalsProvider({
+ defaultLocale: this.currentLocale,
+ fallbackLocale: "en",
+ locales: map
+ });
+ }
+
+ private async readLocalizationDirectory() {
+ const translationFiles = [];
+ const localPath = resolve('assets', 'locals');
+ assert(existsSync(localPath), "No directory \"assets/locals\" found for the localizer")
+ for(const json_path of await fs.readdir(localPath)) {
+ const parsed = JSON.parse(await fs.readFile(join(localPath, json_path), 'utf8'))
+ const name = json_path.substring(0, json_path.lastIndexOf('.'));
+ translationFiles.push({ [name]: parsed })
+ }
+ return translationFiles.reduce((acc, cur) => ({ ...cur, ...acc }), {});
+ }
+}
+
+/**
+ * Translates a string to its respective local
+ * Note: this method only works AFTER your container has been initiated
+ * @example
+ * ```ts
+ * assert.deepEqual(locals("salute.hello", "es"), "hola")
+ * ```
+ */
+export const local = (i: string, local: string) => {
+ return Service('localizer').translate(i, local)
+}
+
+
+
+
+/**
+ * An init plugin to add localization fields to a command module.
+ * Your localization configuration should look like,
+ * @param root {string} If you have conflicting command names, you may configure the root of the name. (= command/{root})
+ * Below is es.json (spanish)
+ * ```json
+ {
+ "command/comer" : {
+ "description": "Comer en Texas",
+ "options": {
+ "chicken": {
+ "name": "pollo",
+ "description": "un pollo largo"
+ }
+ }
+ }
+ }
+ ```
+ */
+export const localize = (root?: string) =>
+ //@ts-ignore
+ CommandInitPlugin(({ module, deps }) => {
+ if(module.type === CommandType.Slash || module.type === CommandType.Both) {
+ deps['@sern/logger'].info({ message: "Localizing "+ module.name });
+ const resolvedLocalization= 'command/'+(root??module.name);
+ Reflect.set(module, 'name_localizations', deps.localizer.translationsFor(resolvedLocalization+".name"));
+ Reflect.set(module, 'description_localizations', deps.localizer.translationsFor(resolvedLocalization+'.description'));
+ const newOpts = module.options ?? [];
+ //@ts-ignore
+ dfsApplyLocalization(newOpts, deps, [resolvedLocalization]);
+ return controller.next();
+ } else {
+ //@ts-ignore
+ return controller.stop("Cannot localize this type of module " + module.name);
+ }
+})
+
+export interface Localizer {
+ /**
+ * Returns an object containing translations for the given path.
+ * The object keys are the translation keys, and the values are the translated strings.
+ *
+ * @param path - The path to the translations file or directory.
+ * @returns An object with translation keys and their corresponding translated strings.
+ */
+ translationsFor(path: string): Record;
+
+ /**
+ * Translates the given text to the specified locale.
+ *
+ * @param text - The text to be translated.
+ * @param locale - The locale to translate the text to.
+ * @returns The translated text.
+ */
+ translate(text: string, locale?: string): string;
+
+ /**
+ * Sets the current locale to be used for translation.
+ * @param locale - The locale to set as the current locale.
+ */
+ setCurrentLocale(locale: string): void;
+}
+
+/**
+ * A service which provides simple file based localization. Add this while making dependencies.
+ * @example
+ * ```ts
+ * await makeDependencies(({ add }) => {
+ * add('localizer', Localization());
+ * });
+ * ```
+ **/
+export const Localization = (defaultLocale?: string) => {
+ const localizer = new ShrimpleLocalizer;
+ if (defaultLocale) {
+ localizer.setCurrentLocale(defaultLocale);
+ }
+ return localizer as Localizer;
+}
diff --git a/packages/localizer/internal.ts b/packages/localizer/internal.ts
new file mode 100644
index 0000000..c8bf6cd
--- /dev/null
+++ b/packages/localizer/internal.ts
@@ -0,0 +1,50 @@
+
+export interface Option {
+ name:string,
+ type: number,
+ options?: Array