inline-i18n-multi 0.1.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/LICENSE +21 -0
- package/dist/index.d.mts +129 -0
- package/dist/index.d.ts +129 -0
- package/dist/index.js +190 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +165 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +46 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Locale code type (e.g., 'ko', 'en', 'ja')
|
|
3
|
+
*/
|
|
4
|
+
type Locale = string;
|
|
5
|
+
/**
|
|
6
|
+
* Translation map with locale keys
|
|
7
|
+
*/
|
|
8
|
+
type Translations = Record<Locale, string>;
|
|
9
|
+
/**
|
|
10
|
+
* Variables for interpolation
|
|
11
|
+
*/
|
|
12
|
+
type TranslationVars = Record<string, string | number>;
|
|
13
|
+
/**
|
|
14
|
+
* Configuration options
|
|
15
|
+
*/
|
|
16
|
+
interface Config {
|
|
17
|
+
defaultLocale: Locale;
|
|
18
|
+
fallbackLocale?: Locale;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Translate with two languages (shorthand)
|
|
23
|
+
* @param ko - Korean text
|
|
24
|
+
* @param en - English text
|
|
25
|
+
* @param vars - Variables for interpolation
|
|
26
|
+
*/
|
|
27
|
+
declare function it(ko: string, en: string, vars?: TranslationVars): string;
|
|
28
|
+
/**
|
|
29
|
+
* Translate with multiple languages (object syntax)
|
|
30
|
+
* @param translations - Translation map with locale keys
|
|
31
|
+
* @param vars - Variables for interpolation
|
|
32
|
+
*/
|
|
33
|
+
declare function it(translations: Translations, vars?: TranslationVars): string;
|
|
34
|
+
|
|
35
|
+
declare function setLocale(locale: Locale): void;
|
|
36
|
+
declare function getLocale(): Locale;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Runtime lookup function for plugin-transformed code.
|
|
40
|
+
* This is called by code that has been processed by @inline-i18n-multi/babel-plugin
|
|
41
|
+
* or @inline-i18n-multi/swc-plugin.
|
|
42
|
+
*
|
|
43
|
+
* @param _hash - Content hash (for caching/debugging, unused at runtime)
|
|
44
|
+
* @param translations - Translation map with locale keys
|
|
45
|
+
* @param vars - Variables for interpolation
|
|
46
|
+
*/
|
|
47
|
+
declare function __i18n_lookup(_hash: string, translations: Translations, vars?: TranslationVars): string;
|
|
48
|
+
|
|
49
|
+
type PairFunction = (text1: string, text2: string, vars?: TranslationVars) => string;
|
|
50
|
+
declare const it_ja: PairFunction;
|
|
51
|
+
declare const it_zh: PairFunction;
|
|
52
|
+
declare const it_es: PairFunction;
|
|
53
|
+
declare const it_fr: PairFunction;
|
|
54
|
+
declare const it_de: PairFunction;
|
|
55
|
+
declare const en_ja: PairFunction;
|
|
56
|
+
declare const en_zh: PairFunction;
|
|
57
|
+
declare const en_es: PairFunction;
|
|
58
|
+
declare const en_fr: PairFunction;
|
|
59
|
+
declare const en_de: PairFunction;
|
|
60
|
+
declare const ja_zh: PairFunction;
|
|
61
|
+
declare const ja_es: PairFunction;
|
|
62
|
+
declare const zh_es: PairFunction;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Nested dictionary structure for translations
|
|
66
|
+
* @example { greeting: { hello: "Hello", goodbye: "Goodbye" } }
|
|
67
|
+
*/
|
|
68
|
+
type Dictionary = {
|
|
69
|
+
[key: string]: string | Dictionary;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* All loaded dictionaries by locale
|
|
73
|
+
*/
|
|
74
|
+
type Dictionaries = Record<Locale, Dictionary>;
|
|
75
|
+
/**
|
|
76
|
+
* Plural rules configuration
|
|
77
|
+
*/
|
|
78
|
+
interface PluralRules {
|
|
79
|
+
zero?: string;
|
|
80
|
+
one?: string;
|
|
81
|
+
two?: string;
|
|
82
|
+
few?: string;
|
|
83
|
+
many?: string;
|
|
84
|
+
other: string;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Load translations from dictionary objects
|
|
88
|
+
* @param dicts - Dictionary objects keyed by locale
|
|
89
|
+
* @example
|
|
90
|
+
* loadDictionaries({
|
|
91
|
+
* en: { greeting: { hello: "Hello" } },
|
|
92
|
+
* ko: { greeting: { hello: "안녕하세요" } }
|
|
93
|
+
* })
|
|
94
|
+
*/
|
|
95
|
+
declare function loadDictionaries(dicts: Dictionaries): void;
|
|
96
|
+
/**
|
|
97
|
+
* Load a single locale's dictionary
|
|
98
|
+
* @param locale - Locale code
|
|
99
|
+
* @param dict - Dictionary object
|
|
100
|
+
*/
|
|
101
|
+
declare function loadDictionary(locale: Locale, dict: Dictionary): void;
|
|
102
|
+
/**
|
|
103
|
+
* Clear all loaded dictionaries
|
|
104
|
+
*/
|
|
105
|
+
declare function clearDictionaries(): void;
|
|
106
|
+
/**
|
|
107
|
+
* Translate using key-based lookup (i18n compatible)
|
|
108
|
+
* @param key - Dot-separated translation key
|
|
109
|
+
* @param vars - Variables for interpolation (including 'count' for plurals)
|
|
110
|
+
* @param locale - Override locale (optional)
|
|
111
|
+
* @example
|
|
112
|
+
* t('greeting.hello') // "Hello"
|
|
113
|
+
* t('items.count', { count: 5 }) // "5 items"
|
|
114
|
+
*/
|
|
115
|
+
declare function t(key: string, vars?: TranslationVars, locale?: Locale): string;
|
|
116
|
+
/**
|
|
117
|
+
* Check if a translation key exists
|
|
118
|
+
*/
|
|
119
|
+
declare function hasTranslation(key: string, locale?: Locale): boolean;
|
|
120
|
+
/**
|
|
121
|
+
* Get all loaded locales
|
|
122
|
+
*/
|
|
123
|
+
declare function getLoadedLocales(): Locale[];
|
|
124
|
+
/**
|
|
125
|
+
* Get dictionary for a specific locale
|
|
126
|
+
*/
|
|
127
|
+
declare function getDictionary(locale: Locale): Dictionary | undefined;
|
|
128
|
+
|
|
129
|
+
export { type Config, type Dictionaries, type Dictionary, type Locale, type PluralRules, type TranslationVars, type Translations, __i18n_lookup, clearDictionaries, en_de, en_es, en_fr, en_ja, en_zh, getDictionary, getLoadedLocales, getLocale, hasTranslation, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, loadDictionaries, loadDictionary, setLocale, t, zh_es };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Locale code type (e.g., 'ko', 'en', 'ja')
|
|
3
|
+
*/
|
|
4
|
+
type Locale = string;
|
|
5
|
+
/**
|
|
6
|
+
* Translation map with locale keys
|
|
7
|
+
*/
|
|
8
|
+
type Translations = Record<Locale, string>;
|
|
9
|
+
/**
|
|
10
|
+
* Variables for interpolation
|
|
11
|
+
*/
|
|
12
|
+
type TranslationVars = Record<string, string | number>;
|
|
13
|
+
/**
|
|
14
|
+
* Configuration options
|
|
15
|
+
*/
|
|
16
|
+
interface Config {
|
|
17
|
+
defaultLocale: Locale;
|
|
18
|
+
fallbackLocale?: Locale;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Translate with two languages (shorthand)
|
|
23
|
+
* @param ko - Korean text
|
|
24
|
+
* @param en - English text
|
|
25
|
+
* @param vars - Variables for interpolation
|
|
26
|
+
*/
|
|
27
|
+
declare function it(ko: string, en: string, vars?: TranslationVars): string;
|
|
28
|
+
/**
|
|
29
|
+
* Translate with multiple languages (object syntax)
|
|
30
|
+
* @param translations - Translation map with locale keys
|
|
31
|
+
* @param vars - Variables for interpolation
|
|
32
|
+
*/
|
|
33
|
+
declare function it(translations: Translations, vars?: TranslationVars): string;
|
|
34
|
+
|
|
35
|
+
declare function setLocale(locale: Locale): void;
|
|
36
|
+
declare function getLocale(): Locale;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Runtime lookup function for plugin-transformed code.
|
|
40
|
+
* This is called by code that has been processed by @inline-i18n-multi/babel-plugin
|
|
41
|
+
* or @inline-i18n-multi/swc-plugin.
|
|
42
|
+
*
|
|
43
|
+
* @param _hash - Content hash (for caching/debugging, unused at runtime)
|
|
44
|
+
* @param translations - Translation map with locale keys
|
|
45
|
+
* @param vars - Variables for interpolation
|
|
46
|
+
*/
|
|
47
|
+
declare function __i18n_lookup(_hash: string, translations: Translations, vars?: TranslationVars): string;
|
|
48
|
+
|
|
49
|
+
type PairFunction = (text1: string, text2: string, vars?: TranslationVars) => string;
|
|
50
|
+
declare const it_ja: PairFunction;
|
|
51
|
+
declare const it_zh: PairFunction;
|
|
52
|
+
declare const it_es: PairFunction;
|
|
53
|
+
declare const it_fr: PairFunction;
|
|
54
|
+
declare const it_de: PairFunction;
|
|
55
|
+
declare const en_ja: PairFunction;
|
|
56
|
+
declare const en_zh: PairFunction;
|
|
57
|
+
declare const en_es: PairFunction;
|
|
58
|
+
declare const en_fr: PairFunction;
|
|
59
|
+
declare const en_de: PairFunction;
|
|
60
|
+
declare const ja_zh: PairFunction;
|
|
61
|
+
declare const ja_es: PairFunction;
|
|
62
|
+
declare const zh_es: PairFunction;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Nested dictionary structure for translations
|
|
66
|
+
* @example { greeting: { hello: "Hello", goodbye: "Goodbye" } }
|
|
67
|
+
*/
|
|
68
|
+
type Dictionary = {
|
|
69
|
+
[key: string]: string | Dictionary;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* All loaded dictionaries by locale
|
|
73
|
+
*/
|
|
74
|
+
type Dictionaries = Record<Locale, Dictionary>;
|
|
75
|
+
/**
|
|
76
|
+
* Plural rules configuration
|
|
77
|
+
*/
|
|
78
|
+
interface PluralRules {
|
|
79
|
+
zero?: string;
|
|
80
|
+
one?: string;
|
|
81
|
+
two?: string;
|
|
82
|
+
few?: string;
|
|
83
|
+
many?: string;
|
|
84
|
+
other: string;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Load translations from dictionary objects
|
|
88
|
+
* @param dicts - Dictionary objects keyed by locale
|
|
89
|
+
* @example
|
|
90
|
+
* loadDictionaries({
|
|
91
|
+
* en: { greeting: { hello: "Hello" } },
|
|
92
|
+
* ko: { greeting: { hello: "안녕하세요" } }
|
|
93
|
+
* })
|
|
94
|
+
*/
|
|
95
|
+
declare function loadDictionaries(dicts: Dictionaries): void;
|
|
96
|
+
/**
|
|
97
|
+
* Load a single locale's dictionary
|
|
98
|
+
* @param locale - Locale code
|
|
99
|
+
* @param dict - Dictionary object
|
|
100
|
+
*/
|
|
101
|
+
declare function loadDictionary(locale: Locale, dict: Dictionary): void;
|
|
102
|
+
/**
|
|
103
|
+
* Clear all loaded dictionaries
|
|
104
|
+
*/
|
|
105
|
+
declare function clearDictionaries(): void;
|
|
106
|
+
/**
|
|
107
|
+
* Translate using key-based lookup (i18n compatible)
|
|
108
|
+
* @param key - Dot-separated translation key
|
|
109
|
+
* @param vars - Variables for interpolation (including 'count' for plurals)
|
|
110
|
+
* @param locale - Override locale (optional)
|
|
111
|
+
* @example
|
|
112
|
+
* t('greeting.hello') // "Hello"
|
|
113
|
+
* t('items.count', { count: 5 }) // "5 items"
|
|
114
|
+
*/
|
|
115
|
+
declare function t(key: string, vars?: TranslationVars, locale?: Locale): string;
|
|
116
|
+
/**
|
|
117
|
+
* Check if a translation key exists
|
|
118
|
+
*/
|
|
119
|
+
declare function hasTranslation(key: string, locale?: Locale): boolean;
|
|
120
|
+
/**
|
|
121
|
+
* Get all loaded locales
|
|
122
|
+
*/
|
|
123
|
+
declare function getLoadedLocales(): Locale[];
|
|
124
|
+
/**
|
|
125
|
+
* Get dictionary for a specific locale
|
|
126
|
+
*/
|
|
127
|
+
declare function getDictionary(locale: Locale): Dictionary | undefined;
|
|
128
|
+
|
|
129
|
+
export { type Config, type Dictionaries, type Dictionary, type Locale, type PluralRules, type TranslationVars, type Translations, __i18n_lookup, clearDictionaries, en_de, en_es, en_fr, en_ja, en_zh, getDictionary, getLoadedLocales, getLocale, hasTranslation, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, loadDictionaries, loadDictionary, setLocale, t, zh_es };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/context.ts
|
|
4
|
+
var currentLocale = "en";
|
|
5
|
+
function setLocale(locale) {
|
|
6
|
+
currentLocale = locale;
|
|
7
|
+
}
|
|
8
|
+
function getLocale() {
|
|
9
|
+
return currentLocale;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// src/interpolation.ts
|
|
13
|
+
var VARIABLE_PATTERN = /\{(\w+)\}/g;
|
|
14
|
+
function interpolate(template, vars) {
|
|
15
|
+
if (!vars) return template;
|
|
16
|
+
return template.replace(VARIABLE_PATTERN, (_, key) => {
|
|
17
|
+
const value = vars[key];
|
|
18
|
+
return value !== void 0 ? String(value) : `{${key}}`;
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// src/translate.ts
|
|
23
|
+
function resolveTemplate(translations) {
|
|
24
|
+
const locale = getLocale();
|
|
25
|
+
const template = translations[locale];
|
|
26
|
+
if (template) return template;
|
|
27
|
+
const fallback = translations.en ?? Object.values(translations)[0];
|
|
28
|
+
if (fallback) return fallback;
|
|
29
|
+
throw new Error(
|
|
30
|
+
`No translation found for locale "${locale}". Available: ${Object.keys(translations).join(", ")}`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
function it(first, second, third) {
|
|
34
|
+
if (typeof first === "object") {
|
|
35
|
+
const translations2 = first;
|
|
36
|
+
const vars2 = second;
|
|
37
|
+
return interpolate(resolveTemplate(translations2), vars2);
|
|
38
|
+
}
|
|
39
|
+
const ko = first;
|
|
40
|
+
const en = second;
|
|
41
|
+
const vars = third;
|
|
42
|
+
const translations = { ko, en };
|
|
43
|
+
return interpolate(resolveTemplate(translations), vars);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// src/runtime.ts
|
|
47
|
+
function __i18n_lookup(_hash, translations, vars) {
|
|
48
|
+
const locale = getLocale();
|
|
49
|
+
const template = translations[locale];
|
|
50
|
+
if (template) {
|
|
51
|
+
return interpolate(template, vars);
|
|
52
|
+
}
|
|
53
|
+
const fallback = translations.en ?? Object.values(translations)[0];
|
|
54
|
+
if (fallback) {
|
|
55
|
+
return interpolate(fallback, vars);
|
|
56
|
+
}
|
|
57
|
+
throw new Error(
|
|
58
|
+
`No translation found for locale "${locale}". Available: ${Object.keys(translations).join(", ")}`
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
if (typeof globalThis !== "undefined") {
|
|
62
|
+
globalThis.__i18n_lookup = __i18n_lookup;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// src/pairs.ts
|
|
66
|
+
function createPair(lang1, lang2) {
|
|
67
|
+
return (text1, text2, vars) => {
|
|
68
|
+
const translations = {
|
|
69
|
+
[lang1]: text1,
|
|
70
|
+
[lang2]: text2
|
|
71
|
+
};
|
|
72
|
+
return it(translations, vars);
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
var it_ja = createPair("ko", "ja");
|
|
76
|
+
var it_zh = createPair("ko", "zh");
|
|
77
|
+
var it_es = createPair("ko", "es");
|
|
78
|
+
var it_fr = createPair("ko", "fr");
|
|
79
|
+
var it_de = createPair("ko", "de");
|
|
80
|
+
var en_ja = createPair("en", "ja");
|
|
81
|
+
var en_zh = createPair("en", "zh");
|
|
82
|
+
var en_es = createPair("en", "es");
|
|
83
|
+
var en_fr = createPair("en", "fr");
|
|
84
|
+
var en_de = createPair("en", "de");
|
|
85
|
+
var ja_zh = createPair("ja", "zh");
|
|
86
|
+
var ja_es = createPair("ja", "es");
|
|
87
|
+
var zh_es = createPair("zh", "es");
|
|
88
|
+
|
|
89
|
+
// src/dictionary.ts
|
|
90
|
+
var VARIABLE_PATTERN2 = /\{(\w+)\}/g;
|
|
91
|
+
var dictionaries = {};
|
|
92
|
+
function loadDictionaries(dicts) {
|
|
93
|
+
dictionaries = { ...dictionaries, ...dicts };
|
|
94
|
+
}
|
|
95
|
+
function loadDictionary(locale, dict) {
|
|
96
|
+
dictionaries[locale] = { ...dictionaries[locale], ...dict };
|
|
97
|
+
}
|
|
98
|
+
function clearDictionaries() {
|
|
99
|
+
dictionaries = {};
|
|
100
|
+
}
|
|
101
|
+
function getNestedValue(dict, key) {
|
|
102
|
+
const parts = key.split(".");
|
|
103
|
+
let current = dict;
|
|
104
|
+
for (const part of parts) {
|
|
105
|
+
if (typeof current !== "object" || current === null) {
|
|
106
|
+
return void 0;
|
|
107
|
+
}
|
|
108
|
+
current = current[part];
|
|
109
|
+
if (current === void 0) {
|
|
110
|
+
return void 0;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return typeof current === "string" ? current : void 0;
|
|
114
|
+
}
|
|
115
|
+
function interpolate2(template, vars) {
|
|
116
|
+
if (!vars) return template;
|
|
117
|
+
return template.replace(VARIABLE_PATTERN2, (_, key) => {
|
|
118
|
+
const value = vars[key];
|
|
119
|
+
return value !== void 0 ? String(value) : `{${key}}`;
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
function getPluralCategory(count, locale) {
|
|
123
|
+
const rules = new Intl.PluralRules(locale);
|
|
124
|
+
return rules.select(count);
|
|
125
|
+
}
|
|
126
|
+
function t(key, vars, locale) {
|
|
127
|
+
const currentLocale2 = locale ?? getLocale();
|
|
128
|
+
const dict = dictionaries[currentLocale2];
|
|
129
|
+
if (!dict) {
|
|
130
|
+
console.warn(`[inline-i18n] No dictionary loaded for locale: ${currentLocale2}`);
|
|
131
|
+
return key;
|
|
132
|
+
}
|
|
133
|
+
let template = getNestedValue(dict, key);
|
|
134
|
+
if (vars && typeof vars.count === "number") {
|
|
135
|
+
const pluralKey = `${key}_${getPluralCategory(vars.count, currentLocale2)}`;
|
|
136
|
+
const pluralTemplate = getNestedValue(dict, pluralKey);
|
|
137
|
+
if (pluralTemplate) {
|
|
138
|
+
template = pluralTemplate;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (!template) {
|
|
142
|
+
const fallbackDict = dictionaries["en"];
|
|
143
|
+
if (fallbackDict && currentLocale2 !== "en") {
|
|
144
|
+
template = getNestedValue(fallbackDict, key);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (!template) {
|
|
148
|
+
console.warn(`[inline-i18n] Missing translation: ${key} (${currentLocale2})`);
|
|
149
|
+
return key;
|
|
150
|
+
}
|
|
151
|
+
return interpolate2(template, vars);
|
|
152
|
+
}
|
|
153
|
+
function hasTranslation(key, locale) {
|
|
154
|
+
const currentLocale2 = locale ?? getLocale();
|
|
155
|
+
const dict = dictionaries[currentLocale2];
|
|
156
|
+
return dict ? getNestedValue(dict, key) !== void 0 : false;
|
|
157
|
+
}
|
|
158
|
+
function getLoadedLocales() {
|
|
159
|
+
return Object.keys(dictionaries);
|
|
160
|
+
}
|
|
161
|
+
function getDictionary(locale) {
|
|
162
|
+
return dictionaries[locale];
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
exports.__i18n_lookup = __i18n_lookup;
|
|
166
|
+
exports.clearDictionaries = clearDictionaries;
|
|
167
|
+
exports.en_de = en_de;
|
|
168
|
+
exports.en_es = en_es;
|
|
169
|
+
exports.en_fr = en_fr;
|
|
170
|
+
exports.en_ja = en_ja;
|
|
171
|
+
exports.en_zh = en_zh;
|
|
172
|
+
exports.getDictionary = getDictionary;
|
|
173
|
+
exports.getLoadedLocales = getLoadedLocales;
|
|
174
|
+
exports.getLocale = getLocale;
|
|
175
|
+
exports.hasTranslation = hasTranslation;
|
|
176
|
+
exports.it = it;
|
|
177
|
+
exports.it_de = it_de;
|
|
178
|
+
exports.it_es = it_es;
|
|
179
|
+
exports.it_fr = it_fr;
|
|
180
|
+
exports.it_ja = it_ja;
|
|
181
|
+
exports.it_zh = it_zh;
|
|
182
|
+
exports.ja_es = ja_es;
|
|
183
|
+
exports.ja_zh = ja_zh;
|
|
184
|
+
exports.loadDictionaries = loadDictionaries;
|
|
185
|
+
exports.loadDictionary = loadDictionary;
|
|
186
|
+
exports.setLocale = setLocale;
|
|
187
|
+
exports.t = t;
|
|
188
|
+
exports.zh_es = zh_es;
|
|
189
|
+
//# sourceMappingURL=index.js.map
|
|
190
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/context.ts","../src/interpolation.ts","../src/translate.ts","../src/runtime.ts","../src/pairs.ts","../src/dictionary.ts"],"names":["translations","vars","VARIABLE_PATTERN","interpolate","currentLocale"],"mappings":"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","file":"index.js","sourcesContent":["import type { Locale } from './types'\n\nlet currentLocale: Locale = 'en'\n\nexport function setLocale(locale: Locale): void {\n currentLocale = locale\n}\n\nexport function getLocale(): Locale {\n return currentLocale\n}\n","import type { TranslationVars } from './types'\n\nconst VARIABLE_PATTERN = /\\{(\\w+)\\}/g\n\nexport function interpolate(\n template: string,\n vars?: TranslationVars,\n): string {\n if (!vars) return template\n\n return template.replace(VARIABLE_PATTERN, (_, key) => {\n const value = vars[key]\n return value !== undefined ? String(value) : `{${key}}`\n })\n}\n","import type { Translations, TranslationVars } from './types'\nimport { getLocale } from './context'\nimport { interpolate } from './interpolation'\n\nfunction resolveTemplate(translations: Translations): string {\n const locale = getLocale()\n\n const template = translations[locale]\n if (template) return template\n\n // fallback: en -> first available\n const fallback = translations.en ?? Object.values(translations)[0]\n if (fallback) return fallback\n\n throw new Error(\n `No translation found for locale \"${locale}\". Available: ${Object.keys(translations).join(', ')}`\n )\n}\n\n/**\n * Translate with two languages (shorthand)\n * @param ko - Korean text\n * @param en - English text\n * @param vars - Variables for interpolation\n */\nexport function it(ko: string, en: string, vars?: TranslationVars): string\n\n/**\n * Translate with multiple languages (object syntax)\n * @param translations - Translation map with locale keys\n * @param vars - Variables for interpolation\n */\nexport function it(translations: Translations, vars?: TranslationVars): string\n\nexport function it(\n first: string | Translations,\n second?: string | TranslationVars,\n third?: TranslationVars,\n): string {\n // object syntax: it({ ko: '...', en: '...' }, vars?)\n if (typeof first === 'object') {\n const translations = first\n const vars = second as TranslationVars | undefined\n return interpolate(resolveTemplate(translations), vars)\n }\n\n // shorthand syntax: it('한글', 'English', vars?)\n const ko = first\n const en = second as string\n const vars = third\n\n const translations: Translations = { ko, en }\n return interpolate(resolveTemplate(translations), vars)\n}\n","import type { Translations, TranslationVars } from './types'\nimport { getLocale } from './context'\nimport { interpolate } from './interpolation'\n\n/**\n * Runtime lookup function for plugin-transformed code.\n * This is called by code that has been processed by @inline-i18n-multi/babel-plugin\n * or @inline-i18n-multi/swc-plugin.\n *\n * @param _hash - Content hash (for caching/debugging, unused at runtime)\n * @param translations - Translation map with locale keys\n * @param vars - Variables for interpolation\n */\nexport function __i18n_lookup(\n _hash: string,\n translations: Translations,\n vars?: TranslationVars\n): string {\n const locale = getLocale()\n\n const template = translations[locale]\n if (template) {\n return interpolate(template, vars)\n }\n\n // fallback: en -> first available\n const fallback = translations.en ?? Object.values(translations)[0]\n if (fallback) {\n return interpolate(fallback, vars)\n }\n\n throw new Error(\n `No translation found for locale \"${locale}\". Available: ${Object.keys(translations).join(', ')}`\n )\n}\n\n// Register __i18n_lookup globally for plugin transformations\n// This makes it available without explicit import after bundle\nif (typeof globalThis !== 'undefined') {\n (globalThis as Record<string, unknown>).__i18n_lookup = __i18n_lookup\n}\n","import type { Locale, Translations, TranslationVars } from './types'\nimport { it } from './translate'\n\ntype PairFunction = (\n text1: string,\n text2: string,\n vars?: TranslationVars,\n) => string\n\nfunction createPair(lang1: Locale, lang2: Locale): PairFunction {\n return (text1, text2, vars) => {\n const translations: Translations = {\n [lang1]: text1,\n [lang2]: text2,\n }\n return it(translations, vars)\n }\n}\n\n// Korean combinations\nexport const it_ja = createPair('ko', 'ja')\nexport const it_zh = createPair('ko', 'zh')\nexport const it_es = createPair('ko', 'es')\nexport const it_fr = createPair('ko', 'fr')\nexport const it_de = createPair('ko', 'de')\n\n// English combinations\nexport const en_ja = createPair('en', 'ja')\nexport const en_zh = createPair('en', 'zh')\nexport const en_es = createPair('en', 'es')\nexport const en_fr = createPair('en', 'fr')\nexport const en_de = createPair('en', 'de')\n\n// Other combinations\nexport const ja_zh = createPair('ja', 'zh')\nexport const ja_es = createPair('ja', 'es')\nexport const zh_es = createPair('zh', 'es')\n","import { getLocale } from './context'\nimport type { Locale, TranslationVars } from './types'\n\n/**\n * Nested dictionary structure for translations\n * @example { greeting: { hello: \"Hello\", goodbye: \"Goodbye\" } }\n */\nexport type Dictionary = {\n [key: string]: string | Dictionary\n}\n\n/**\n * All loaded dictionaries by locale\n */\nexport type Dictionaries = Record<Locale, Dictionary>\n\n/**\n * Plural rules configuration\n */\nexport interface PluralRules {\n zero?: string\n one?: string\n two?: string\n few?: string\n many?: string\n other: string\n}\n\nconst VARIABLE_PATTERN = /\\{(\\w+)\\}/g\n\n// Global dictionary storage\nlet dictionaries: Dictionaries = {}\n\n/**\n * Load translations from dictionary objects\n * @param dicts - Dictionary objects keyed by locale\n * @example\n * loadDictionaries({\n * en: { greeting: { hello: \"Hello\" } },\n * ko: { greeting: { hello: \"안녕하세요\" } }\n * })\n */\nexport function loadDictionaries(dicts: Dictionaries): void {\n dictionaries = { ...dictionaries, ...dicts }\n}\n\n/**\n * Load a single locale's dictionary\n * @param locale - Locale code\n * @param dict - Dictionary object\n */\nexport function loadDictionary(locale: Locale, dict: Dictionary): void {\n dictionaries[locale] = { ...dictionaries[locale], ...dict }\n}\n\n/**\n * Clear all loaded dictionaries\n */\nexport function clearDictionaries(): void {\n dictionaries = {}\n}\n\n/**\n * Get a nested value from dictionary using dot notation\n * @param dict - Dictionary object\n * @param key - Dot-separated key path\n */\nfunction getNestedValue(dict: Dictionary, key: string): string | undefined {\n const parts = key.split('.')\n let current: string | Dictionary | undefined = dict\n\n for (const part of parts) {\n if (typeof current !== 'object' || current === null) {\n return undefined\n }\n current = current[part]\n if (current === undefined) {\n return undefined\n }\n }\n\n return typeof current === 'string' ? current : undefined\n}\n\n/**\n * Interpolate variables into template string\n */\nfunction interpolate(template: string, vars?: TranslationVars): string {\n if (!vars) return template\n\n return template.replace(VARIABLE_PATTERN, (_, key) => {\n const value = vars[key]\n return value !== undefined ? String(value) : `{${key}}`\n })\n}\n\n/**\n * Get plural category using Intl.PluralRules\n */\nfunction getPluralCategory(count: number, locale: Locale): Intl.LDMLPluralRule {\n const rules = new Intl.PluralRules(locale)\n return rules.select(count)\n}\n\n/**\n * Translate using key-based lookup (i18n compatible)\n * @param key - Dot-separated translation key\n * @param vars - Variables for interpolation (including 'count' for plurals)\n * @param locale - Override locale (optional)\n * @example\n * t('greeting.hello') // \"Hello\"\n * t('items.count', { count: 5 }) // \"5 items\"\n */\nexport function t(\n key: string,\n vars?: TranslationVars,\n locale?: Locale\n): string {\n const currentLocale = locale ?? getLocale()\n const dict = dictionaries[currentLocale]\n\n if (!dict) {\n console.warn(`[inline-i18n] No dictionary loaded for locale: ${currentLocale}`)\n return key\n }\n\n let template = getNestedValue(dict, key)\n\n // Handle plurals if count is provided\n if (vars && typeof vars.count === 'number') {\n const pluralKey = `${key}_${getPluralCategory(vars.count, currentLocale)}`\n const pluralTemplate = getNestedValue(dict, pluralKey)\n if (pluralTemplate) {\n template = pluralTemplate\n }\n }\n\n if (!template) {\n // Try fallback to English\n const fallbackDict = dictionaries['en']\n if (fallbackDict && currentLocale !== 'en') {\n template = getNestedValue(fallbackDict, key)\n }\n }\n\n if (!template) {\n console.warn(`[inline-i18n] Missing translation: ${key} (${currentLocale})`)\n return key\n }\n\n return interpolate(template, vars)\n}\n\n/**\n * Check if a translation key exists\n */\nexport function hasTranslation(key: string, locale?: Locale): boolean {\n const currentLocale = locale ?? getLocale()\n const dict = dictionaries[currentLocale]\n return dict ? getNestedValue(dict, key) !== undefined : false\n}\n\n/**\n * Get all loaded locales\n */\nexport function getLoadedLocales(): Locale[] {\n return Object.keys(dictionaries)\n}\n\n/**\n * Get dictionary for a specific locale\n */\nexport function getDictionary(locale: Locale): Dictionary | undefined {\n return dictionaries[locale]\n}\n"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// src/context.ts
|
|
2
|
+
var currentLocale = "en";
|
|
3
|
+
function setLocale(locale) {
|
|
4
|
+
currentLocale = locale;
|
|
5
|
+
}
|
|
6
|
+
function getLocale() {
|
|
7
|
+
return currentLocale;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// src/interpolation.ts
|
|
11
|
+
var VARIABLE_PATTERN = /\{(\w+)\}/g;
|
|
12
|
+
function interpolate(template, vars) {
|
|
13
|
+
if (!vars) return template;
|
|
14
|
+
return template.replace(VARIABLE_PATTERN, (_, key) => {
|
|
15
|
+
const value = vars[key];
|
|
16
|
+
return value !== void 0 ? String(value) : `{${key}}`;
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// src/translate.ts
|
|
21
|
+
function resolveTemplate(translations) {
|
|
22
|
+
const locale = getLocale();
|
|
23
|
+
const template = translations[locale];
|
|
24
|
+
if (template) return template;
|
|
25
|
+
const fallback = translations.en ?? Object.values(translations)[0];
|
|
26
|
+
if (fallback) return fallback;
|
|
27
|
+
throw new Error(
|
|
28
|
+
`No translation found for locale "${locale}". Available: ${Object.keys(translations).join(", ")}`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
function it(first, second, third) {
|
|
32
|
+
if (typeof first === "object") {
|
|
33
|
+
const translations2 = first;
|
|
34
|
+
const vars2 = second;
|
|
35
|
+
return interpolate(resolveTemplate(translations2), vars2);
|
|
36
|
+
}
|
|
37
|
+
const ko = first;
|
|
38
|
+
const en = second;
|
|
39
|
+
const vars = third;
|
|
40
|
+
const translations = { ko, en };
|
|
41
|
+
return interpolate(resolveTemplate(translations), vars);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// src/runtime.ts
|
|
45
|
+
function __i18n_lookup(_hash, translations, vars) {
|
|
46
|
+
const locale = getLocale();
|
|
47
|
+
const template = translations[locale];
|
|
48
|
+
if (template) {
|
|
49
|
+
return interpolate(template, vars);
|
|
50
|
+
}
|
|
51
|
+
const fallback = translations.en ?? Object.values(translations)[0];
|
|
52
|
+
if (fallback) {
|
|
53
|
+
return interpolate(fallback, vars);
|
|
54
|
+
}
|
|
55
|
+
throw new Error(
|
|
56
|
+
`No translation found for locale "${locale}". Available: ${Object.keys(translations).join(", ")}`
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
if (typeof globalThis !== "undefined") {
|
|
60
|
+
globalThis.__i18n_lookup = __i18n_lookup;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// src/pairs.ts
|
|
64
|
+
function createPair(lang1, lang2) {
|
|
65
|
+
return (text1, text2, vars) => {
|
|
66
|
+
const translations = {
|
|
67
|
+
[lang1]: text1,
|
|
68
|
+
[lang2]: text2
|
|
69
|
+
};
|
|
70
|
+
return it(translations, vars);
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
var it_ja = createPair("ko", "ja");
|
|
74
|
+
var it_zh = createPair("ko", "zh");
|
|
75
|
+
var it_es = createPair("ko", "es");
|
|
76
|
+
var it_fr = createPair("ko", "fr");
|
|
77
|
+
var it_de = createPair("ko", "de");
|
|
78
|
+
var en_ja = createPair("en", "ja");
|
|
79
|
+
var en_zh = createPair("en", "zh");
|
|
80
|
+
var en_es = createPair("en", "es");
|
|
81
|
+
var en_fr = createPair("en", "fr");
|
|
82
|
+
var en_de = createPair("en", "de");
|
|
83
|
+
var ja_zh = createPair("ja", "zh");
|
|
84
|
+
var ja_es = createPair("ja", "es");
|
|
85
|
+
var zh_es = createPair("zh", "es");
|
|
86
|
+
|
|
87
|
+
// src/dictionary.ts
|
|
88
|
+
var VARIABLE_PATTERN2 = /\{(\w+)\}/g;
|
|
89
|
+
var dictionaries = {};
|
|
90
|
+
function loadDictionaries(dicts) {
|
|
91
|
+
dictionaries = { ...dictionaries, ...dicts };
|
|
92
|
+
}
|
|
93
|
+
function loadDictionary(locale, dict) {
|
|
94
|
+
dictionaries[locale] = { ...dictionaries[locale], ...dict };
|
|
95
|
+
}
|
|
96
|
+
function clearDictionaries() {
|
|
97
|
+
dictionaries = {};
|
|
98
|
+
}
|
|
99
|
+
function getNestedValue(dict, key) {
|
|
100
|
+
const parts = key.split(".");
|
|
101
|
+
let current = dict;
|
|
102
|
+
for (const part of parts) {
|
|
103
|
+
if (typeof current !== "object" || current === null) {
|
|
104
|
+
return void 0;
|
|
105
|
+
}
|
|
106
|
+
current = current[part];
|
|
107
|
+
if (current === void 0) {
|
|
108
|
+
return void 0;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return typeof current === "string" ? current : void 0;
|
|
112
|
+
}
|
|
113
|
+
function interpolate2(template, vars) {
|
|
114
|
+
if (!vars) return template;
|
|
115
|
+
return template.replace(VARIABLE_PATTERN2, (_, key) => {
|
|
116
|
+
const value = vars[key];
|
|
117
|
+
return value !== void 0 ? String(value) : `{${key}}`;
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
function getPluralCategory(count, locale) {
|
|
121
|
+
const rules = new Intl.PluralRules(locale);
|
|
122
|
+
return rules.select(count);
|
|
123
|
+
}
|
|
124
|
+
function t(key, vars, locale) {
|
|
125
|
+
const currentLocale2 = locale ?? getLocale();
|
|
126
|
+
const dict = dictionaries[currentLocale2];
|
|
127
|
+
if (!dict) {
|
|
128
|
+
console.warn(`[inline-i18n] No dictionary loaded for locale: ${currentLocale2}`);
|
|
129
|
+
return key;
|
|
130
|
+
}
|
|
131
|
+
let template = getNestedValue(dict, key);
|
|
132
|
+
if (vars && typeof vars.count === "number") {
|
|
133
|
+
const pluralKey = `${key}_${getPluralCategory(vars.count, currentLocale2)}`;
|
|
134
|
+
const pluralTemplate = getNestedValue(dict, pluralKey);
|
|
135
|
+
if (pluralTemplate) {
|
|
136
|
+
template = pluralTemplate;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (!template) {
|
|
140
|
+
const fallbackDict = dictionaries["en"];
|
|
141
|
+
if (fallbackDict && currentLocale2 !== "en") {
|
|
142
|
+
template = getNestedValue(fallbackDict, key);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (!template) {
|
|
146
|
+
console.warn(`[inline-i18n] Missing translation: ${key} (${currentLocale2})`);
|
|
147
|
+
return key;
|
|
148
|
+
}
|
|
149
|
+
return interpolate2(template, vars);
|
|
150
|
+
}
|
|
151
|
+
function hasTranslation(key, locale) {
|
|
152
|
+
const currentLocale2 = locale ?? getLocale();
|
|
153
|
+
const dict = dictionaries[currentLocale2];
|
|
154
|
+
return dict ? getNestedValue(dict, key) !== void 0 : false;
|
|
155
|
+
}
|
|
156
|
+
function getLoadedLocales() {
|
|
157
|
+
return Object.keys(dictionaries);
|
|
158
|
+
}
|
|
159
|
+
function getDictionary(locale) {
|
|
160
|
+
return dictionaries[locale];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export { __i18n_lookup, clearDictionaries, en_de, en_es, en_fr, en_ja, en_zh, getDictionary, getLoadedLocales, getLocale, hasTranslation, it, it_de, it_es, it_fr, it_ja, it_zh, ja_es, ja_zh, loadDictionaries, loadDictionary, setLocale, t, zh_es };
|
|
164
|
+
//# sourceMappingURL=index.mjs.map
|
|
165
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/context.ts","../src/interpolation.ts","../src/translate.ts","../src/runtime.ts","../src/pairs.ts","../src/dictionary.ts"],"names":["translations","vars","VARIABLE_PATTERN","interpolate","currentLocale"],"mappings":"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","file":"index.mjs","sourcesContent":["import type { Locale } from './types'\n\nlet currentLocale: Locale = 'en'\n\nexport function setLocale(locale: Locale): void {\n currentLocale = locale\n}\n\nexport function getLocale(): Locale {\n return currentLocale\n}\n","import type { TranslationVars } from './types'\n\nconst VARIABLE_PATTERN = /\\{(\\w+)\\}/g\n\nexport function interpolate(\n template: string,\n vars?: TranslationVars,\n): string {\n if (!vars) return template\n\n return template.replace(VARIABLE_PATTERN, (_, key) => {\n const value = vars[key]\n return value !== undefined ? String(value) : `{${key}}`\n })\n}\n","import type { Translations, TranslationVars } from './types'\nimport { getLocale } from './context'\nimport { interpolate } from './interpolation'\n\nfunction resolveTemplate(translations: Translations): string {\n const locale = getLocale()\n\n const template = translations[locale]\n if (template) return template\n\n // fallback: en -> first available\n const fallback = translations.en ?? Object.values(translations)[0]\n if (fallback) return fallback\n\n throw new Error(\n `No translation found for locale \"${locale}\". Available: ${Object.keys(translations).join(', ')}`\n )\n}\n\n/**\n * Translate with two languages (shorthand)\n * @param ko - Korean text\n * @param en - English text\n * @param vars - Variables for interpolation\n */\nexport function it(ko: string, en: string, vars?: TranslationVars): string\n\n/**\n * Translate with multiple languages (object syntax)\n * @param translations - Translation map with locale keys\n * @param vars - Variables for interpolation\n */\nexport function it(translations: Translations, vars?: TranslationVars): string\n\nexport function it(\n first: string | Translations,\n second?: string | TranslationVars,\n third?: TranslationVars,\n): string {\n // object syntax: it({ ko: '...', en: '...' }, vars?)\n if (typeof first === 'object') {\n const translations = first\n const vars = second as TranslationVars | undefined\n return interpolate(resolveTemplate(translations), vars)\n }\n\n // shorthand syntax: it('한글', 'English', vars?)\n const ko = first\n const en = second as string\n const vars = third\n\n const translations: Translations = { ko, en }\n return interpolate(resolveTemplate(translations), vars)\n}\n","import type { Translations, TranslationVars } from './types'\nimport { getLocale } from './context'\nimport { interpolate } from './interpolation'\n\n/**\n * Runtime lookup function for plugin-transformed code.\n * This is called by code that has been processed by @inline-i18n-multi/babel-plugin\n * or @inline-i18n-multi/swc-plugin.\n *\n * @param _hash - Content hash (for caching/debugging, unused at runtime)\n * @param translations - Translation map with locale keys\n * @param vars - Variables for interpolation\n */\nexport function __i18n_lookup(\n _hash: string,\n translations: Translations,\n vars?: TranslationVars\n): string {\n const locale = getLocale()\n\n const template = translations[locale]\n if (template) {\n return interpolate(template, vars)\n }\n\n // fallback: en -> first available\n const fallback = translations.en ?? Object.values(translations)[0]\n if (fallback) {\n return interpolate(fallback, vars)\n }\n\n throw new Error(\n `No translation found for locale \"${locale}\". Available: ${Object.keys(translations).join(', ')}`\n )\n}\n\n// Register __i18n_lookup globally for plugin transformations\n// This makes it available without explicit import after bundle\nif (typeof globalThis !== 'undefined') {\n (globalThis as Record<string, unknown>).__i18n_lookup = __i18n_lookup\n}\n","import type { Locale, Translations, TranslationVars } from './types'\nimport { it } from './translate'\n\ntype PairFunction = (\n text1: string,\n text2: string,\n vars?: TranslationVars,\n) => string\n\nfunction createPair(lang1: Locale, lang2: Locale): PairFunction {\n return (text1, text2, vars) => {\n const translations: Translations = {\n [lang1]: text1,\n [lang2]: text2,\n }\n return it(translations, vars)\n }\n}\n\n// Korean combinations\nexport const it_ja = createPair('ko', 'ja')\nexport const it_zh = createPair('ko', 'zh')\nexport const it_es = createPair('ko', 'es')\nexport const it_fr = createPair('ko', 'fr')\nexport const it_de = createPair('ko', 'de')\n\n// English combinations\nexport const en_ja = createPair('en', 'ja')\nexport const en_zh = createPair('en', 'zh')\nexport const en_es = createPair('en', 'es')\nexport const en_fr = createPair('en', 'fr')\nexport const en_de = createPair('en', 'de')\n\n// Other combinations\nexport const ja_zh = createPair('ja', 'zh')\nexport const ja_es = createPair('ja', 'es')\nexport const zh_es = createPair('zh', 'es')\n","import { getLocale } from './context'\nimport type { Locale, TranslationVars } from './types'\n\n/**\n * Nested dictionary structure for translations\n * @example { greeting: { hello: \"Hello\", goodbye: \"Goodbye\" } }\n */\nexport type Dictionary = {\n [key: string]: string | Dictionary\n}\n\n/**\n * All loaded dictionaries by locale\n */\nexport type Dictionaries = Record<Locale, Dictionary>\n\n/**\n * Plural rules configuration\n */\nexport interface PluralRules {\n zero?: string\n one?: string\n two?: string\n few?: string\n many?: string\n other: string\n}\n\nconst VARIABLE_PATTERN = /\\{(\\w+)\\}/g\n\n// Global dictionary storage\nlet dictionaries: Dictionaries = {}\n\n/**\n * Load translations from dictionary objects\n * @param dicts - Dictionary objects keyed by locale\n * @example\n * loadDictionaries({\n * en: { greeting: { hello: \"Hello\" } },\n * ko: { greeting: { hello: \"안녕하세요\" } }\n * })\n */\nexport function loadDictionaries(dicts: Dictionaries): void {\n dictionaries = { ...dictionaries, ...dicts }\n}\n\n/**\n * Load a single locale's dictionary\n * @param locale - Locale code\n * @param dict - Dictionary object\n */\nexport function loadDictionary(locale: Locale, dict: Dictionary): void {\n dictionaries[locale] = { ...dictionaries[locale], ...dict }\n}\n\n/**\n * Clear all loaded dictionaries\n */\nexport function clearDictionaries(): void {\n dictionaries = {}\n}\n\n/**\n * Get a nested value from dictionary using dot notation\n * @param dict - Dictionary object\n * @param key - Dot-separated key path\n */\nfunction getNestedValue(dict: Dictionary, key: string): string | undefined {\n const parts = key.split('.')\n let current: string | Dictionary | undefined = dict\n\n for (const part of parts) {\n if (typeof current !== 'object' || current === null) {\n return undefined\n }\n current = current[part]\n if (current === undefined) {\n return undefined\n }\n }\n\n return typeof current === 'string' ? current : undefined\n}\n\n/**\n * Interpolate variables into template string\n */\nfunction interpolate(template: string, vars?: TranslationVars): string {\n if (!vars) return template\n\n return template.replace(VARIABLE_PATTERN, (_, key) => {\n const value = vars[key]\n return value !== undefined ? String(value) : `{${key}}`\n })\n}\n\n/**\n * Get plural category using Intl.PluralRules\n */\nfunction getPluralCategory(count: number, locale: Locale): Intl.LDMLPluralRule {\n const rules = new Intl.PluralRules(locale)\n return rules.select(count)\n}\n\n/**\n * Translate using key-based lookup (i18n compatible)\n * @param key - Dot-separated translation key\n * @param vars - Variables for interpolation (including 'count' for plurals)\n * @param locale - Override locale (optional)\n * @example\n * t('greeting.hello') // \"Hello\"\n * t('items.count', { count: 5 }) // \"5 items\"\n */\nexport function t(\n key: string,\n vars?: TranslationVars,\n locale?: Locale\n): string {\n const currentLocale = locale ?? getLocale()\n const dict = dictionaries[currentLocale]\n\n if (!dict) {\n console.warn(`[inline-i18n] No dictionary loaded for locale: ${currentLocale}`)\n return key\n }\n\n let template = getNestedValue(dict, key)\n\n // Handle plurals if count is provided\n if (vars && typeof vars.count === 'number') {\n const pluralKey = `${key}_${getPluralCategory(vars.count, currentLocale)}`\n const pluralTemplate = getNestedValue(dict, pluralKey)\n if (pluralTemplate) {\n template = pluralTemplate\n }\n }\n\n if (!template) {\n // Try fallback to English\n const fallbackDict = dictionaries['en']\n if (fallbackDict && currentLocale !== 'en') {\n template = getNestedValue(fallbackDict, key)\n }\n }\n\n if (!template) {\n console.warn(`[inline-i18n] Missing translation: ${key} (${currentLocale})`)\n return key\n }\n\n return interpolate(template, vars)\n}\n\n/**\n * Check if a translation key exists\n */\nexport function hasTranslation(key: string, locale?: Locale): boolean {\n const currentLocale = locale ?? getLocale()\n const dict = dictionaries[currentLocale]\n return dict ? getNestedValue(dict, key) !== undefined : false\n}\n\n/**\n * Get all loaded locales\n */\nexport function getLoadedLocales(): Locale[] {\n return Object.keys(dictionaries)\n}\n\n/**\n * Get dictionary for a specific locale\n */\nexport function getDictionary(locale: Locale): Dictionary | undefined {\n return dictionaries[locale]\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "inline-i18n-multi",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Inline i18n - write translations inline, support multiple languages",
|
|
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
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"sideEffects": false,
|
|
19
|
+
"keywords": [
|
|
20
|
+
"i18n",
|
|
21
|
+
"internationalization",
|
|
22
|
+
"translation",
|
|
23
|
+
"inline",
|
|
24
|
+
"multi-language"
|
|
25
|
+
],
|
|
26
|
+
"author": "exiivy98",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/exiivy98/inline-i18n-multi.git",
|
|
31
|
+
"directory": "packages/core"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"tsup": "^8.3.5",
|
|
35
|
+
"typescript": "^5.7.2",
|
|
36
|
+
"vitest": "^2.1.8"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsup",
|
|
40
|
+
"dev": "tsup --watch",
|
|
41
|
+
"test": "vitest",
|
|
42
|
+
"lint": "eslint src",
|
|
43
|
+
"typecheck": "tsc --noEmit",
|
|
44
|
+
"clean": "rm -rf dist"
|
|
45
|
+
}
|
|
46
|
+
}
|