lite-i18n 1.0.1-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -0
- package/dist/index.d.mts +38 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +34 -0
package/README.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# lite-i18n
|
|
2
|
+
|
|
3
|
+
A lightweight, type-safe string translation library for TypeScript/JavaScript.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 📦 **Universal**: Works with Parcel, Vite, Webpack, Rollup, esbuild
|
|
8
|
+
- 🚀 **Lightweight**: Zero dependencies, tiny bundle size
|
|
9
|
+
- 🔒 **Type-Safe**: Full TypeScript support
|
|
10
|
+
- 🧩 **Simple API**: Dot notation for nested keys, interpolation support
|
|
11
|
+
- 🔢 **Pluralization**: Supports both key-based (`_plural` suffix) and inline pluralization
|
|
12
|
+
- 🎨 **Rich Text**: Support for HTML/Rich Text interpolation
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install lite-i18n
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
### Basic Usage
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { createTranslator } from 'lite-i18n';
|
|
26
|
+
|
|
27
|
+
const translations = {
|
|
28
|
+
en: {
|
|
29
|
+
greeting: 'Hello, {{name}}!',
|
|
30
|
+
messages: {
|
|
31
|
+
unread: 'You have {{count}} unread messages'
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
es: {
|
|
35
|
+
greeting: '¡Hola, {{name}}!',
|
|
36
|
+
messages: {
|
|
37
|
+
unread: 'Tienes {{count}} mensajes no leÃdos'
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const t = createTranslator('en', translations);
|
|
43
|
+
|
|
44
|
+
console.log(t('greeting', { name: 'Alice' })); // "Hello, Alice!"
|
|
45
|
+
console.log(t('messages.unread', { count: 5 })); // "You have 5 unread messages"
|
|
46
|
+
|
|
47
|
+
t.setLocale('es');
|
|
48
|
+
console.log(t('greeting', { name: 'Bob' })); // "¡Hola, Bob!"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Pluralization
|
|
52
|
+
|
|
53
|
+
#### Key-based Pluralization
|
|
54
|
+
Automatically detects if a `count` variable is passed and looks for a `_plural` key.
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
const translations = {
|
|
58
|
+
en: {
|
|
59
|
+
items: {
|
|
60
|
+
cart: 'One item in cart',
|
|
61
|
+
cart_plural: '{{count}} items in cart'
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const t = createTranslator('en', translations);
|
|
67
|
+
|
|
68
|
+
t.t('items.cart', { count: 1 }); // "One item in cart"
|
|
69
|
+
t.t('items.cart', { count: 5 }); // "5 items in cart"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
#### Inline Pluralization
|
|
73
|
+
Define plural forms directly in your code (useful for view-specific logic).
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
const clicks = 2;
|
|
77
|
+
const text = t.plural(clicks, {
|
|
78
|
+
one: 'You clicked once',
|
|
79
|
+
other: 'You clicked {{count}} times',
|
|
80
|
+
zero: 'No clicks yet' // Optional zero state
|
|
81
|
+
});
|
|
82
|
+
// "You clicked 2 times"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### HTML / Rich Text
|
|
86
|
+
You can pass HTML strings as variables to inject rich text.
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
const translations = {
|
|
90
|
+
en: {
|
|
91
|
+
welcome: 'Welcome, <b>{{name}}</b>!'
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
// ...
|
|
95
|
+
const html = t.t('welcome', { name: '<span class="user">Admin</span>' });
|
|
96
|
+
// "Welcome, <b><span class="user">Admin</span></b>!"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Declarative Translation
|
|
100
|
+
You can automatically translate elements using `data-i18n` attributes.
|
|
101
|
+
|
|
102
|
+
```html
|
|
103
|
+
<h1 data-i18n="global.title"></h1>
|
|
104
|
+
<p data-i18n="messages.unread" data-i18n-vars='{"count": 5}'></p>
|
|
105
|
+
|
|
106
|
+
<!-- For HTML content (uses innerHTML) -->
|
|
107
|
+
<div data-i18n-html="html.welcome"></div>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
t.autoTranslate();
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
This method scans for `data-i18n` (sets `textContent`) and `data-i18n-html` (sets `innerHTML`), parsing optional `data-i18n-vars` (JSON).
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
type Variables = Record<string, string | number | boolean | null | undefined>;
|
|
2
|
+
type Translations = {
|
|
3
|
+
[key: string]: string | Translations;
|
|
4
|
+
};
|
|
5
|
+
interface TranslatorOptions {
|
|
6
|
+
locale: string;
|
|
7
|
+
translations: Record<string, Translations>;
|
|
8
|
+
fallbackLocale?: string;
|
|
9
|
+
debug?: boolean;
|
|
10
|
+
}
|
|
11
|
+
interface PluralOptions {
|
|
12
|
+
count: number;
|
|
13
|
+
one: string;
|
|
14
|
+
other: string;
|
|
15
|
+
zero?: string;
|
|
16
|
+
[key: string]: any;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
declare class Translator {
|
|
20
|
+
private locale;
|
|
21
|
+
private translations;
|
|
22
|
+
private fallbackLocale?;
|
|
23
|
+
constructor(options: TranslatorOptions);
|
|
24
|
+
t(key: string, variables?: Variables): string;
|
|
25
|
+
plural(count: number, options: Omit<PluralOptions, 'count'>): string;
|
|
26
|
+
setLocale(locale: string): void;
|
|
27
|
+
getLocale(): string;
|
|
28
|
+
private getTranslation;
|
|
29
|
+
private interpolate;
|
|
30
|
+
/**
|
|
31
|
+
* Auto-translate all elements with data-i18n attribute
|
|
32
|
+
*/
|
|
33
|
+
autoTranslate(): void;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
declare function createTranslator(locale: string, translations: Record<string, Translations>, options?: Partial<Omit<TranslatorOptions, 'locale' | 'translations'>>): Translator;
|
|
37
|
+
|
|
38
|
+
export { type Translations, Translator, type TranslatorOptions, createTranslator };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
type Variables = Record<string, string | number | boolean | null | undefined>;
|
|
2
|
+
type Translations = {
|
|
3
|
+
[key: string]: string | Translations;
|
|
4
|
+
};
|
|
5
|
+
interface TranslatorOptions {
|
|
6
|
+
locale: string;
|
|
7
|
+
translations: Record<string, Translations>;
|
|
8
|
+
fallbackLocale?: string;
|
|
9
|
+
debug?: boolean;
|
|
10
|
+
}
|
|
11
|
+
interface PluralOptions {
|
|
12
|
+
count: number;
|
|
13
|
+
one: string;
|
|
14
|
+
other: string;
|
|
15
|
+
zero?: string;
|
|
16
|
+
[key: string]: any;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
declare class Translator {
|
|
20
|
+
private locale;
|
|
21
|
+
private translations;
|
|
22
|
+
private fallbackLocale?;
|
|
23
|
+
constructor(options: TranslatorOptions);
|
|
24
|
+
t(key: string, variables?: Variables): string;
|
|
25
|
+
plural(count: number, options: Omit<PluralOptions, 'count'>): string;
|
|
26
|
+
setLocale(locale: string): void;
|
|
27
|
+
getLocale(): string;
|
|
28
|
+
private getTranslation;
|
|
29
|
+
private interpolate;
|
|
30
|
+
/**
|
|
31
|
+
* Auto-translate all elements with data-i18n attribute
|
|
32
|
+
*/
|
|
33
|
+
autoTranslate(): void;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
declare function createTranslator(locale: string, translations: Record<string, Translations>, options?: Partial<Omit<TranslatorOptions, 'locale' | 'translations'>>): Translator;
|
|
37
|
+
|
|
38
|
+
export { type Translations, Translator, type TranslatorOptions, createTranslator };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var s=Object.defineProperty;var o=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var u=Object.prototype.hasOwnProperty;var f=(n,t)=>{for(var a in t)s(n,a,{get:t[a],enumerable:!0})},p=(n,t,a,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of c(t))!u.call(n,r)&&r!==a&&s(n,r,{get:()=>t[r],enumerable:!(e=o(t,r))||e.enumerable});return n};var g=n=>p(s({},"__esModule",{value:!0}),n);var b={};f(b,{Translator:()=>i,createTranslator:()=>h});module.exports=g(b);var i=class{constructor(t){this.locale=t.locale,this.translations=t.translations,this.fallbackLocale=t.fallbackLocale}t(t,a){let e=t;if(a&&typeof a.count=="number"&&a.count!==1){let l=`${t}_plural`;(this.getTranslation(this.locale,l)||this.fallbackLocale&&this.getTranslation(this.fallbackLocale,l))&&(e=l)}let r=this.getTranslation(this.locale,e);return!r&&this.fallbackLocale&&(r=this.getTranslation(this.fallbackLocale,e)),r?this.interpolate(r,a):t}plural(t,a){let e={count:t,...a},r=a.other;return t===0&&a.zero?r=a.zero:t===1&&(r=a.one),this.interpolate(r,e)}setLocale(t){this.locale=t}getLocale(){return this.locale}getTranslation(t,a){let e=a.split("."),r=this.translations[t];for(let l of e)if(r&&typeof r=="object"&&l in r)r=r[l];else return null;return typeof r=="string"?r:null}interpolate(t,a){return a?t.replace(/\{\{\s*([a-zA-Z0-9_]+)\s*\}\}/g,(e,r)=>{let l=a[r];return l==null?`{{${r}}}`:String(l)}):t}autoTranslate(){typeof document>"u"||(document.querySelectorAll("[data-i18n]").forEach(t=>{let a=t.getAttribute("data-i18n");if(!a)return;let e=t.getAttribute("data-i18n-vars"),r=e?JSON.parse(e):void 0;t.textContent=this.t(a,r)}),document.querySelectorAll("[data-i18n-html]").forEach(t=>{let a=t.getAttribute("data-i18n-html");if(!a)return;let e=t.getAttribute("data-i18n-vars"),r=e?JSON.parse(e):void 0;t.innerHTML=this.t(a,r)}))}};function h(n,t,a){return new i({locale:n,translations:t,...a})}0&&(module.exports={Translator,createTranslator});
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/translator.ts"],"sourcesContent":["import { Translator } from './translator';\nimport { Translations, TranslatorOptions } from './types';\n\nexport { Translator, Translations, TranslatorOptions };\n\nexport function createTranslator(locale: string, translations: Record<string, Translations>, options?: Partial<Omit<TranslatorOptions, 'locale' | 'translations'>>) {\n return new Translator({\n locale,\n translations,\n ...options\n });\n}\n","import { Translations, Variables, TranslatorOptions, PluralOptions } from './types';\n\nexport class Translator {\n private locale: string;\n private translations: Record<string, Translations>;\n private fallbackLocale?: string;\n\n constructor(options: TranslatorOptions) {\n this.locale = options.locale;\n this.translations = options.translations;\n this.fallbackLocale = options.fallbackLocale;\n }\n\n public t(key: string, variables?: Variables): string {\n let lookupKey = key;\n\n // Simple pluralization: if count is provided and not 1, look for _plural key\n if (variables && typeof variables.count === 'number' && variables.count !== 1) {\n const pluralKey = `${key}_plural`;\n if (this.getTranslation(this.locale, pluralKey) || (this.fallbackLocale && this.getTranslation(this.fallbackLocale, pluralKey))) {\n lookupKey = pluralKey;\n }\n }\n\n let template = this.getTranslation(this.locale, lookupKey);\n\n if (!template && this.fallbackLocale) {\n template = this.getTranslation(this.fallbackLocale, lookupKey);\n }\n\n if (!template) {\n // Fallback to original key if translation missing\n return key;\n }\n\n return this.interpolate(template, variables);\n }\n\n public plural(count: number, options: Omit<PluralOptions, 'count'>): string {\n const vars: Variables = { count, ...options };\n let template = options.other;\n\n if (count === 0 && options.zero) {\n template = options.zero;\n } else if (count === 1) {\n template = options.one;\n }\n\n return this.interpolate(template, vars);\n }\n\n public setLocale(locale: string): void {\n this.locale = locale;\n }\n\n public getLocale(): string {\n return this.locale;\n }\n\n private getTranslation(locale: string, key: string): string | null {\n const keys = key.split('.');\n let current: any = this.translations[locale];\n\n for (const k of keys) {\n if (current && typeof current === 'object' && k in current) {\n current = current[k];\n } else {\n return null;\n }\n }\n\n return typeof current === 'string' ? current : null;\n }\n\n private interpolate(template: string, variables?: Variables): string {\n if (!variables) {\n return template;\n }\n\n return template.replace(/\\{\\{\\s*([a-zA-Z0-9_]+)\\s*\\}\\}/g, (_, key) => {\n const value = variables[key];\n if (value === undefined || value === null) {\n return `{{${key}}}`;\n }\n return String(value);\n });\n }\n\n /**\n * Auto-translate all elements with data-i18n attribute\n */\n public autoTranslate(): void {\n if (typeof document === 'undefined') return;\n\n // Handle standard text translations (safe)\n document.querySelectorAll('[data-i18n]').forEach((el: Element) => {\n const key = el.getAttribute('data-i18n');\n if (!key) return;\n\n const varsAttr = el.getAttribute('data-i18n-vars');\n const variables = varsAttr ? JSON.parse(varsAttr) : undefined;\n\n (el as HTMLElement).textContent = this.t(key, variables);\n });\n\n // Handle HTML translations\n document.querySelectorAll('[data-i18n-html]').forEach((el: Element) => {\n const key = el.getAttribute('data-i18n-html');\n if (!key) return;\n\n const varsAttr = el.getAttribute('data-i18n-vars');\n const variables = varsAttr ? JSON.parse(varsAttr) : undefined;\n\n (el as HTMLElement).innerHTML = this.t(key, variables);\n });\n }\n}\n"],"mappings":"yaAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,gBAAAE,EAAA,qBAAAC,IAAA,eAAAC,EAAAJ,GCEO,IAAMK,EAAN,KAAiB,CAKpB,YAAYC,EAA4B,CACpC,KAAK,OAASA,EAAQ,OACtB,KAAK,aAAeA,EAAQ,aAC5B,KAAK,eAAiBA,EAAQ,cAClC,CAEO,EAAEC,EAAaC,EAA+B,CACjD,IAAIC,EAAYF,EAGhB,GAAIC,GAAa,OAAOA,EAAU,OAAU,UAAYA,EAAU,QAAU,EAAG,CAC3E,IAAME,EAAY,GAAGH,CAAG,WACpB,KAAK,eAAe,KAAK,OAAQG,CAAS,GAAM,KAAK,gBAAkB,KAAK,eAAe,KAAK,eAAgBA,CAAS,KACzHD,EAAYC,EAEpB,CAEA,IAAIC,EAAW,KAAK,eAAe,KAAK,OAAQF,CAAS,EAMzD,MAJI,CAACE,GAAY,KAAK,iBAClBA,EAAW,KAAK,eAAe,KAAK,eAAgBF,CAAS,GAG5DE,EAKE,KAAK,YAAYA,EAAUH,CAAS,EAHhCD,CAIf,CAEO,OAAOK,EAAeN,EAA+C,CACxE,IAAMO,EAAkB,CAAE,MAAAD,EAAO,GAAGN,CAAQ,EACxCK,EAAWL,EAAQ,MAEvB,OAAIM,IAAU,GAAKN,EAAQ,KACvBK,EAAWL,EAAQ,KACZM,IAAU,IACjBD,EAAWL,EAAQ,KAGhB,KAAK,YAAYK,EAAUE,CAAI,CAC1C,CAEO,UAAUC,EAAsB,CACnC,KAAK,OAASA,CAClB,CAEO,WAAoB,CACvB,OAAO,KAAK,MAChB,CAEQ,eAAeA,EAAgBP,EAA4B,CAC/D,IAAMQ,EAAOR,EAAI,MAAM,GAAG,EACtBS,EAAe,KAAK,aAAaF,CAAM,EAE3C,QAAWG,KAAKF,EACZ,GAAIC,GAAW,OAAOA,GAAY,UAAYC,KAAKD,EAC/CA,EAAUA,EAAQC,CAAC,MAEnB,QAAO,KAIf,OAAO,OAAOD,GAAY,SAAWA,EAAU,IACnD,CAEQ,YAAYL,EAAkBH,EAA+B,CACjE,OAAKA,EAIEG,EAAS,QAAQ,iCAAkC,CAACO,EAAGX,IAAQ,CAClE,IAAMY,EAAQX,EAAUD,CAAG,EAC3B,OAA2BY,GAAU,KAC1B,KAAKZ,CAAG,KAEZ,OAAOY,CAAK,CACvB,CAAC,EATUR,CAUf,CAKO,eAAsB,CACrB,OAAO,SAAa,MAGxB,SAAS,iBAAiB,aAAa,EAAE,QAASS,GAAgB,CAC9D,IAAMb,EAAMa,EAAG,aAAa,WAAW,EACvC,GAAI,CAACb,EAAK,OAEV,IAAMc,EAAWD,EAAG,aAAa,gBAAgB,EAC3CZ,EAAYa,EAAW,KAAK,MAAMA,CAAQ,EAAI,OAEnDD,EAAmB,YAAc,KAAK,EAAEb,EAAKC,CAAS,CAC3D,CAAC,EAGD,SAAS,iBAAiB,kBAAkB,EAAE,QAASY,GAAgB,CACnE,IAAMb,EAAMa,EAAG,aAAa,gBAAgB,EAC5C,GAAI,CAACb,EAAK,OAEV,IAAMc,EAAWD,EAAG,aAAa,gBAAgB,EAC3CZ,EAAYa,EAAW,KAAK,MAAMA,CAAQ,EAAI,OAEnDD,EAAmB,UAAY,KAAK,EAAEb,EAAKC,CAAS,CACzD,CAAC,EACL,CACJ,ED/GO,SAASc,EAAiBC,EAAgBC,EAA4CC,EAAuE,CAChK,OAAO,IAAIC,EAAW,CAClB,OAAAH,EACA,aAAAC,EACA,GAAGC,CACP,CAAC,CACL","names":["index_exports","__export","Translator","createTranslator","__toCommonJS","Translator","options","key","variables","lookupKey","pluralKey","template","count","vars","locale","keys","current","k","_","value","el","varsAttr","createTranslator","locale","translations","options","Translator"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var l=class{constructor(t){this.locale=t.locale,this.translations=t.translations,this.fallbackLocale=t.fallbackLocale}t(t,r){let e=t;if(r&&typeof r.count=="number"&&r.count!==1){let n=`${t}_plural`;(this.getTranslation(this.locale,n)||this.fallbackLocale&&this.getTranslation(this.fallbackLocale,n))&&(e=n)}let a=this.getTranslation(this.locale,e);return!a&&this.fallbackLocale&&(a=this.getTranslation(this.fallbackLocale,e)),a?this.interpolate(a,r):t}plural(t,r){let e={count:t,...r},a=r.other;return t===0&&r.zero?a=r.zero:t===1&&(a=r.one),this.interpolate(a,e)}setLocale(t){this.locale=t}getLocale(){return this.locale}getTranslation(t,r){let e=r.split("."),a=this.translations[t];for(let n of e)if(a&&typeof a=="object"&&n in a)a=a[n];else return null;return typeof a=="string"?a:null}interpolate(t,r){return r?t.replace(/\{\{\s*([a-zA-Z0-9_]+)\s*\}\}/g,(e,a)=>{let n=r[a];return n==null?`{{${a}}}`:String(n)}):t}autoTranslate(){typeof document>"u"||(document.querySelectorAll("[data-i18n]").forEach(t=>{let r=t.getAttribute("data-i18n");if(!r)return;let e=t.getAttribute("data-i18n-vars"),a=e?JSON.parse(e):void 0;t.textContent=this.t(r,a)}),document.querySelectorAll("[data-i18n-html]").forEach(t=>{let r=t.getAttribute("data-i18n-html");if(!r)return;let e=t.getAttribute("data-i18n-vars"),a=e?JSON.parse(e):void 0;t.innerHTML=this.t(r,a)}))}};function c(i,t,r){return new l({locale:i,translations:t,...r})}export{l as Translator,c as createTranslator};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/translator.ts","../src/index.ts"],"sourcesContent":["import { Translations, Variables, TranslatorOptions, PluralOptions } from './types';\n\nexport class Translator {\n private locale: string;\n private translations: Record<string, Translations>;\n private fallbackLocale?: string;\n\n constructor(options: TranslatorOptions) {\n this.locale = options.locale;\n this.translations = options.translations;\n this.fallbackLocale = options.fallbackLocale;\n }\n\n public t(key: string, variables?: Variables): string {\n let lookupKey = key;\n\n // Simple pluralization: if count is provided and not 1, look for _plural key\n if (variables && typeof variables.count === 'number' && variables.count !== 1) {\n const pluralKey = `${key}_plural`;\n if (this.getTranslation(this.locale, pluralKey) || (this.fallbackLocale && this.getTranslation(this.fallbackLocale, pluralKey))) {\n lookupKey = pluralKey;\n }\n }\n\n let template = this.getTranslation(this.locale, lookupKey);\n\n if (!template && this.fallbackLocale) {\n template = this.getTranslation(this.fallbackLocale, lookupKey);\n }\n\n if (!template) {\n // Fallback to original key if translation missing\n return key;\n }\n\n return this.interpolate(template, variables);\n }\n\n public plural(count: number, options: Omit<PluralOptions, 'count'>): string {\n const vars: Variables = { count, ...options };\n let template = options.other;\n\n if (count === 0 && options.zero) {\n template = options.zero;\n } else if (count === 1) {\n template = options.one;\n }\n\n return this.interpolate(template, vars);\n }\n\n public setLocale(locale: string): void {\n this.locale = locale;\n }\n\n public getLocale(): string {\n return this.locale;\n }\n\n private getTranslation(locale: string, key: string): string | null {\n const keys = key.split('.');\n let current: any = this.translations[locale];\n\n for (const k of keys) {\n if (current && typeof current === 'object' && k in current) {\n current = current[k];\n } else {\n return null;\n }\n }\n\n return typeof current === 'string' ? current : null;\n }\n\n private interpolate(template: string, variables?: Variables): string {\n if (!variables) {\n return template;\n }\n\n return template.replace(/\\{\\{\\s*([a-zA-Z0-9_]+)\\s*\\}\\}/g, (_, key) => {\n const value = variables[key];\n if (value === undefined || value === null) {\n return `{{${key}}}`;\n }\n return String(value);\n });\n }\n\n /**\n * Auto-translate all elements with data-i18n attribute\n */\n public autoTranslate(): void {\n if (typeof document === 'undefined') return;\n\n // Handle standard text translations (safe)\n document.querySelectorAll('[data-i18n]').forEach((el: Element) => {\n const key = el.getAttribute('data-i18n');\n if (!key) return;\n\n const varsAttr = el.getAttribute('data-i18n-vars');\n const variables = varsAttr ? JSON.parse(varsAttr) : undefined;\n\n (el as HTMLElement).textContent = this.t(key, variables);\n });\n\n // Handle HTML translations\n document.querySelectorAll('[data-i18n-html]').forEach((el: Element) => {\n const key = el.getAttribute('data-i18n-html');\n if (!key) return;\n\n const varsAttr = el.getAttribute('data-i18n-vars');\n const variables = varsAttr ? JSON.parse(varsAttr) : undefined;\n\n (el as HTMLElement).innerHTML = this.t(key, variables);\n });\n }\n}\n","import { Translator } from './translator';\nimport { Translations, TranslatorOptions } from './types';\n\nexport { Translator, Translations, TranslatorOptions };\n\nexport function createTranslator(locale: string, translations: Record<string, Translations>, options?: Partial<Omit<TranslatorOptions, 'locale' | 'translations'>>) {\n return new Translator({\n locale,\n translations,\n ...options\n });\n}\n"],"mappings":"AAEO,IAAMA,EAAN,KAAiB,CAKpB,YAAYC,EAA4B,CACpC,KAAK,OAASA,EAAQ,OACtB,KAAK,aAAeA,EAAQ,aAC5B,KAAK,eAAiBA,EAAQ,cAClC,CAEO,EAAEC,EAAaC,EAA+B,CACjD,IAAIC,EAAYF,EAGhB,GAAIC,GAAa,OAAOA,EAAU,OAAU,UAAYA,EAAU,QAAU,EAAG,CAC3E,IAAME,EAAY,GAAGH,CAAG,WACpB,KAAK,eAAe,KAAK,OAAQG,CAAS,GAAM,KAAK,gBAAkB,KAAK,eAAe,KAAK,eAAgBA,CAAS,KACzHD,EAAYC,EAEpB,CAEA,IAAIC,EAAW,KAAK,eAAe,KAAK,OAAQF,CAAS,EAMzD,MAJI,CAACE,GAAY,KAAK,iBAClBA,EAAW,KAAK,eAAe,KAAK,eAAgBF,CAAS,GAG5DE,EAKE,KAAK,YAAYA,EAAUH,CAAS,EAHhCD,CAIf,CAEO,OAAOK,EAAeN,EAA+C,CACxE,IAAMO,EAAkB,CAAE,MAAAD,EAAO,GAAGN,CAAQ,EACxCK,EAAWL,EAAQ,MAEvB,OAAIM,IAAU,GAAKN,EAAQ,KACvBK,EAAWL,EAAQ,KACZM,IAAU,IACjBD,EAAWL,EAAQ,KAGhB,KAAK,YAAYK,EAAUE,CAAI,CAC1C,CAEO,UAAUC,EAAsB,CACnC,KAAK,OAASA,CAClB,CAEO,WAAoB,CACvB,OAAO,KAAK,MAChB,CAEQ,eAAeA,EAAgBP,EAA4B,CAC/D,IAAMQ,EAAOR,EAAI,MAAM,GAAG,EACtBS,EAAe,KAAK,aAAaF,CAAM,EAE3C,QAAWG,KAAKF,EACZ,GAAIC,GAAW,OAAOA,GAAY,UAAYC,KAAKD,EAC/CA,EAAUA,EAAQC,CAAC,MAEnB,QAAO,KAIf,OAAO,OAAOD,GAAY,SAAWA,EAAU,IACnD,CAEQ,YAAYL,EAAkBH,EAA+B,CACjE,OAAKA,EAIEG,EAAS,QAAQ,iCAAkC,CAACO,EAAGX,IAAQ,CAClE,IAAMY,EAAQX,EAAUD,CAAG,EAC3B,OAA2BY,GAAU,KAC1B,KAAKZ,CAAG,KAEZ,OAAOY,CAAK,CACvB,CAAC,EATUR,CAUf,CAKO,eAAsB,CACrB,OAAO,SAAa,MAGxB,SAAS,iBAAiB,aAAa,EAAE,QAASS,GAAgB,CAC9D,IAAMb,EAAMa,EAAG,aAAa,WAAW,EACvC,GAAI,CAACb,EAAK,OAEV,IAAMc,EAAWD,EAAG,aAAa,gBAAgB,EAC3CZ,EAAYa,EAAW,KAAK,MAAMA,CAAQ,EAAI,OAEnDD,EAAmB,YAAc,KAAK,EAAEb,EAAKC,CAAS,CAC3D,CAAC,EAGD,SAAS,iBAAiB,kBAAkB,EAAE,QAASY,GAAgB,CACnE,IAAMb,EAAMa,EAAG,aAAa,gBAAgB,EAC5C,GAAI,CAACb,EAAK,OAEV,IAAMc,EAAWD,EAAG,aAAa,gBAAgB,EAC3CZ,EAAYa,EAAW,KAAK,MAAMA,CAAQ,EAAI,OAEnDD,EAAmB,UAAY,KAAK,EAAEb,EAAKC,CAAS,CACzD,CAAC,EACL,CACJ,EC/GO,SAASc,EAAiBC,EAAgBC,EAA4CC,EAAuE,CAChK,OAAO,IAAIC,EAAW,CAClB,OAAAH,EACA,aAAAC,EACA,GAAGC,CACP,CAAC,CACL","names":["Translator","options","key","variables","lookupKey","pluralKey","template","count","vars","locale","keys","current","k","_","value","el","varsAttr","createTranslator","locale","translations","options","Translator"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lite-i18n",
|
|
3
|
+
"version": "1.0.1-beta.0",
|
|
4
|
+
"description": "Lightweight string translation library",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"require": "./dist/index.js",
|
|
12
|
+
"import": "./dist/index.mjs"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup",
|
|
20
|
+
"dev": "tsup --watch",
|
|
21
|
+
"prepublishOnly": "npm run build"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"tsup": "^8.0.0",
|
|
25
|
+
"typescript": "^5.0.0"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"i18n",
|
|
29
|
+
"translation",
|
|
30
|
+
"localization",
|
|
31
|
+
"typescript"
|
|
32
|
+
],
|
|
33
|
+
"license": "MIT"
|
|
34
|
+
}
|