@stacksjs/i18n 0.70.86 → 0.70.88

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stacksjs/i18n",
3
- "version": "0.70.86",
3
+ "version": "0.70.88",
4
4
  "description": "Internationalization system for Stacks.js applications",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -27,8 +27,7 @@
27
27
  "module": "./dist/index.js",
28
28
  "types": "./dist/index.d.ts",
29
29
  "files": [
30
- "dist",
31
- "src"
30
+ "dist"
32
31
  ],
33
32
  "scripts": {
34
33
  "build": "bun build.ts",
@@ -41,6 +40,16 @@
41
40
  "@stacksjs/ts-i18n": "^0.1.9"
42
41
  },
43
42
  "devDependencies": {
44
- "@stacksjs/development": "0.70.86"
43
+ "@stacksjs/development": "0.70.88"
44
+ },
45
+ "publishConfig": {
46
+ "exports": {
47
+ ".": {
48
+ "types": "./dist/index.d.ts",
49
+ "bun": "./dist/index.js",
50
+ "import": "./dist/index.js",
51
+ "default": "./dist/index.js"
52
+ }
53
+ }
45
54
  }
46
55
  }
@@ -1,14 +0,0 @@
1
- /**
2
- * Load translation files from the project `locales/` directory once.
3
- * Locale subdirectories (`locales/de.yml`, `locales/en.yml`, …) are detected
4
- * automatically by `loadFromDirectory`.
5
- */
6
- export declare function ensureLocalesLoaded(): Promise<void>;
7
- /**
8
- * Resolve the active locale for an HTTP request.
9
- * Order: STX locale prefix (`/en/...`), `?locale=`, `locale` cookie,
10
- * Accept-Language, then `config.app.locale`.
11
- */
12
- export declare function resolveRequestLocale(request?: Request): string;
13
- /** Load `locales/` and activate the global translator for this request. */
14
- export declare function applyRequestLocale(request?: Request): Promise<string>;
@@ -1,105 +0,0 @@
1
- /**
2
- * Format a date
3
- */
4
- export declare function formatDate(date: Date | number | string, style?: DateStyle | DateFormatOptions, locale?: string): string;
5
- /**
6
- * Format a time
7
- */
8
- export declare function formatTime(date: Date | number | string, style?: TimeStyle | DateFormatOptions, locale?: string): string;
9
- /**
10
- * Format a date and time
11
- */
12
- export declare function formatDateTime(date: Date | number | string, dateStyle?: DateStyle, timeStyle?: TimeStyle, locale?: string): string;
13
- /**
14
- * Format relative time (e.g., "2 days ago", "in 3 hours")
15
- */
16
- export declare function formatRelativeTime(date: Date | number | string, baseDate?: Date | number | string, style?: 'long' | 'short' | 'narrow', locale?: string): string;
17
- /**
18
- * Format a number
19
- */
20
- export declare function formatNumber(value: number, options?: NumberFormatOptions, locale?: string): string;
21
- /**
22
- * Format a currency value
23
- */
24
- export declare function formatCurrency(value: number, currency?: string, options?: Omit<NumberFormatOptions, 'style' | 'currency'>, locale?: string): string;
25
- /**
26
- * Format a percentage
27
- */
28
- export declare function formatPercent(value: number, options?: Omit<NumberFormatOptions, 'style'>, locale?: string): string;
29
- /**
30
- * Format a number with units (e.g., "5 kilograms", "10 miles")
31
- */
32
- export declare function formatUnit(value: number, unit: string, unitDisplay?: 'long' | 'short' | 'narrow', locale?: string): string;
33
- /**
34
- * Format bytes to human-readable format
35
- */
36
- export declare function formatBytes(bytes: number, decimals?: number, locale?: string): string;
37
- /**
38
- * Format a list of items
39
- */
40
- export declare function formatList(items: string[], type?: ListType, style?: ListStyle, locale?: string): string;
41
- /**
42
- * Get the plural category for a number
43
- */
44
- export declare function formatPlural(value: number, locale?: string): Intl.LDMLPluralRule;
45
- /**
46
- * Select from plural options based on a number
47
- */
48
- export declare function selectPlural<T>(value: number, options: Partial<Record<Intl.LDMLPluralRule, T>> & { other: T }, locale?: string): T;
49
- /**
50
- * Get display name for a code
51
- */
52
- export declare function getDisplayName(code: string, type?: DisplayNameType, style?: 'long' | 'short' | 'narrow', locale?: string): string | undefined;
53
- /**
54
- * Get language name
55
- */
56
- export declare function getLanguageName(languageCode: string, locale?: string): string | undefined;
57
- /**
58
- * Get region/country name
59
- */
60
- export declare function getRegionName(regionCode: string, locale?: string): string | undefined;
61
- /**
62
- * Get currency name
63
- */
64
- export declare function getCurrencyName(currencyCode: string, locale?: string): string | undefined;
65
- /**
66
- * Compare strings in a locale-aware manner
67
- */
68
- export declare function compareStrings(a: string, b: string, options?: Intl.CollatorOptions, locale?: string): number;
69
- /**
70
- * Sort an array of strings in locale-aware order
71
- */
72
- export declare function sortStrings(strings: string[], options?: Intl.CollatorOptions, locale?: string): string[];
73
- /**
74
- * Get the text direction for a locale
75
- */
76
- export declare function getTextDirection(locale?: string): 'ltr' | 'rtl';
77
- /**
78
- * Check if a locale uses RTL text direction
79
- */
80
- export declare function isRTL(locale?: string): boolean;
81
- export declare interface DateFormatOptions extends Intl.DateTimeFormatOptions {
82
- dateStyle?: DateStyle
83
- timeStyle?: TimeStyle
84
- }
85
- // =============================================================================
86
- // Number Formatting
87
- // =============================================================================
88
- export declare interface NumberFormatOptions extends Intl.NumberFormatOptions {
89
- compact?: boolean
90
- precision?: number
91
- }
92
- // =============================================================================
93
- // Date Formatting
94
- // =============================================================================
95
- export type DateStyle = 'full' | 'long' | 'medium' | 'short';
96
- export type TimeStyle = 'full' | 'long' | 'medium' | 'short';
97
- // =============================================================================
98
- // List Formatting
99
- // =============================================================================
100
- export type ListType = 'conjunction' | 'disjunction' | 'unit';
101
- export type ListStyle = 'long' | 'short' | 'narrow';
102
- // =============================================================================
103
- // Display Names
104
- // =============================================================================
105
- export type DisplayNameType = 'language' | 'region' | 'script' | 'currency' | 'calendar' | 'dateTimeField';
package/dist/index.d.ts DELETED
@@ -1,94 +0,0 @@
1
- export type { I18nConfig as TsI18nConfig, TranslationTree, TranslationValue } from '@stacksjs/ts-i18n';
2
- /**
3
- * Stacks i18n - Internationalization System
4
- *
5
- * A comprehensive internationalization system with support for:
6
- * - Translation loading from JSON/YAML files
7
- * - Plural forms
8
- * - Variable interpolation
9
- * - Nested translations
10
- * - Date/time formatting
11
- * - Number formatting
12
- * - Currency formatting
13
- * - Relative time formatting
14
- *
15
- * @example
16
- * ```ts
17
- * import { t, setLocale, addTranslations } from '@stacksjs/i18n'
18
- *
19
- * // Add translations
20
- * addTranslations('en', {
21
- * greeting: 'Hello, {name}!',
22
- * items: '{count} item | {count} items',
23
- * })
24
- *
25
- * // Use translations
26
- * t('greeting', { name: 'World' }) // "Hello, World!"
27
- * t('items', { count: 1 }) // "1 item"
28
- * t('items', { count: 5 }) // "5 items"
29
- *
30
- * // Format dates and numbers
31
- * formatDate(new Date(), 'long') // "January 8, 2026"
32
- * formatNumber(1234567.89) // "1,234,567.89"
33
- * formatCurrency(99.99, 'USD') // "$99.99"
34
- * ```
35
- */
36
- export * from './translator';
37
- export * from './formatter';
38
- export * from './pluralization';
39
- export * from './loader';
40
- export * from './types';
41
- // Re-export the file-loading and type-generation surface from
42
- // `@stacksjs/ts-i18n`. The library handles disk loading (YAML / TS /
43
- // JSON), namespace resolution, and `.d.ts` codegen for translation
44
- // keys; the Stacks-side translator/formatter sits on top of that
45
- // data with locale management, ICU pluralization, and Intl-backed
46
- // formatters. Importing both names from `@stacksjs/i18n` keeps the
47
- // app side from caring which symbol comes from which package.
48
- export {
49
- loadTranslations as loadTranslationsFromDisk,
50
- generateTypes as generateI18nTypes,
51
- generateTypesFromModule as generateI18nTypesFromModule,
52
- generateSampleConfig as generateI18nSampleConfig,
53
- writeOutputs as writeI18nOutputs,
54
- createTranslator as createSimpleTranslator,
55
- } from '@stacksjs/ts-i18n';
56
- // Re-export main functions for convenience
57
- export {
58
- t,
59
- trans,
60
- tc,
61
- te,
62
- tm,
63
- setLocale,
64
- getLocale,
65
- addTranslations,
66
- loadTranslations,
67
- getAvailableLocales,
68
- hasTranslation,
69
- I18n,
70
- createI18n,
71
- useI18n,
72
- } from './translator';
73
- export {
74
- ensureLocalesLoaded,
75
- resolveRequestLocale,
76
- applyRequestLocale,
77
- } from './bootstrap';
78
- export {
79
- createLocaleSwitchResponse,
80
- localizePath,
81
- stripLocalePrefix,
82
- type LocaleSwitchConfig,
83
- } from './locale-switch';
84
- export {
85
- formatDate,
86
- formatTime,
87
- formatDateTime,
88
- formatNumber,
89
- formatCurrency,
90
- formatPercent,
91
- formatRelativeTime,
92
- formatList,
93
- formatPlural,
94
- } from './formatter';
package/dist/index.js DELETED
@@ -1,2 +0,0 @@
1
- // @bun
2
- var x=import.meta.require;function M(q,B){return D(B)(q)}function D(q){let B=q.split("-")[0]?.toLowerCase()??q.toLowerCase(),G=E[B];if(G)return G;return()=>"other"}function c(q,B="|"){let G=q.split(B).map((K)=>K.trim()),J=new Map;if(G.length===1)J.set("other",G[0]??"");else if(G.length===2)J.set("one",G[0]??""),J.set("other",G[1]??"");else if(G.length===3)J.set("zero",G[0]??""),J.set("one",G[1]??""),J.set("other",G[2]??"");else if(G.length>=4){let K=["zero","one","two","few","many","other"];for(let Q=0;Q<G.length&&Q<K.length;Q++){let X=K[Q],U=G[Q];if(X!==void 0&&U!==void 0)J.set(X,U)}}return J}function r(q,B,G){let J=M(B,G);if(q.has(J))return q.get(J);if(q.has("other"))return q.get("other");let K=q.values().next();return K.done?"":K.value}var E={en:(q)=>q===1?"one":"other",de:(q)=>q===1?"one":"other",nl:(q)=>q===1?"one":"other",es:(q)=>q===1?"one":"other",it:(q)=>q===1?"one":"other",pt:(q)=>q===1?"one":"other",sv:(q)=>q===1?"one":"other",da:(q)=>q===1?"one":"other",no:(q)=>q===1?"one":"other",fi:(q)=>q===1?"one":"other",el:(q)=>q===1?"one":"other",he:(q)=>q===1?"one":"other",hu:(q)=>q===1?"one":"other",tr:(q)=>q===1?"one":"other",zh:()=>"other",ja:()=>"other",ko:()=>"other",vi:()=>"other",th:()=>"other",id:()=>"other",ms:()=>"other",fr:(q)=>q===0||q===1?"one":"other",ru:(q)=>{let B=q%10,G=q%100;if(B===1&&G!==11)return"one";if(B>=2&&B<=4&&(G<12||G>14))return"few";if(B===0||B>=5&&B<=9||G>=11&&G<=14)return"many";return"other"},uk:(q)=>{let B=q%10,G=q%100;if(B===1&&G!==11)return"one";if(B>=2&&B<=4&&(G<12||G>14))return"few";if(B===0||B>=5&&B<=9||G>=11&&G<=14)return"many";return"other"},pl:(q)=>{let B=q%10,G=q%100;if(q===1)return"one";if(B>=2&&B<=4&&(G<12||G>14))return"few";if(B===0||B===1||B>=5&&B<=9||G>=12&&G<=14)return"many";return"other"},cs:(q)=>{if(q===1)return"one";if(q>=2&&q<=4)return"few";return"other"},sk:(q)=>{if(q===1)return"one";if(q>=2&&q<=4)return"few";return"other"},ar:(q)=>{if(q===0)return"zero";if(q===1)return"one";if(q===2)return"two";let B=q%100;if(B>=3&&B<=10)return"few";if(B>=11&&B<=99)return"many";return"other"},cy:(q)=>{if(q===0)return"zero";if(q===1)return"one";if(q===2)return"two";if(q===3)return"few";if(q===6)return"many";return"other"},sl:(q)=>{let B=q%100;if(B===1)return"one";if(B===2)return"two";if(B===3||B===4)return"few";return"other"},ga:(q)=>{if(q===1)return"one";if(q===2)return"two";if(q>=3&&q<=6)return"few";if(q>=7&&q<=10)return"many";return"other"},lt:(q)=>{let B=q%10,G=q%100;if(B===1&&(G<11||G>19))return"one";if(B>=2&&B<=9&&(G<11||G>19))return"few";return"other"},lv:(q)=>{let B=q%10,G=q%100;if(q===0)return"zero";if(B===1&&G!==11)return"one";return"other"},ro:(q)=>{if(q===1)return"one";let B=q%100;if(q===0||B>=1&&B<=19)return"few";return"other"},hi:(q)=>q===0||q===1?"one":"other"};function n(){return Object.keys(E)}function s(q){return(q.split("-")[0]?.toLowerCase()??q.toLowerCase())in E}function t(q,B){let G=q.split("-")[0]?.toLowerCase()??q.toLowerCase();E[G]=B}var b={locale:"en",fallbackLocale:"en",availableLocales:["en"],messages:{},warnMissing:!0,escapeValues:!1,keySeparator:".",pluralSeparator:"|"},C="en",O="en",W={},F={...b};function $(){return C}function l(q){O=q}function z(q,B){if(!W[q])W[q]={};W[q]=j(W[q],B)}function Y(q){for(let[B,G]of Object.entries(q))z(B,G)}function a(q){if(F={...F,...q},q.locale)C=q.locale;if(q.fallbackLocale)O=q.fallbackLocale;if(q.messages)Y(q.messages)}function j(q,B){let G={...q};for(let J of Object.keys(B)){let K=B[J],Q=G[J];if(typeof K==="object"&&K!==null&&typeof Q==="object"&&Q!==null)G[J]=j(Q,K);else if(K!==void 0)G[J]=K}return G}function Bq(q,B,G="short",J){let K=J||$();return new Intl.NumberFormat(K,{style:"unit",unit:B,unitDisplay:G}).format(q)}function Gq(q,B=2,G){let J=G||$();if(q===0)return"0 B";let K=1024,Q=["B","KB","MB","GB","TB","PB","EB","ZB","YB"],X=Math.floor(Math.log(q)/Math.log(K)),U=q/Math.pow(K,X);return`${new Intl.NumberFormat(J,{minimumFractionDigits:0,maximumFractionDigits:B}).format(U)} ${Q[X]}`}function h(q,B){let G=B||$();return new Intl.PluralRules(G).select(q)}function Jq(q,B,G){let J=h(q,G);return B[J]??B.other}function I(q,B="language",G="long",J){let K=J||$();try{return new Intl.DisplayNames(K,{type:B,style:G}).of(q)}catch{return}}function Kq(q,B){return I(q,"language","long",B)}function Qq(q,B){return I(q,"region","long",B)}function Uq(q,B){return I(q,"currency","long",B)}function Xq(q,B,G={},J){let K=J||$();return new Intl.Collator(K,G).compare(q,B)}function Zq(q,B={},G){let J=G||$(),K=new Intl.Collator(J,B);return[...q].sort((Q,X)=>K.compare(Q,X))}function v(q){let B=q||$(),G=(B.split("-")[0]??B).toLowerCase();return["ar","he","fa","ur","yi","ps","sd","ug","ku","ckb"].includes(G)?"rtl":"ltr"}function _q(q){return v(q)==="rtl"}import{existsSync as L,readdirSync as S}from"fs";import{readFile as k}from"fs/promises";import{basename as V,extname as w,join as H}from"path";import{log as f}from"@stacksjs/logging";async function y(q){let{directory:B,extensions:G=[".json",".yaml",".yml",".ts",".js"],recursive:J=!1,namespaceSeparator:K="."}=q,Q={};if(!L(B))return f.warn(`[i18n] Translation directory not found: ${B}`),Q;return await P(B,Q,G,J,K,""),Y(Q),Q}async function P(q,B,G,J,K,Q){let X=S(q,{withFileTypes:!0});for(let U of X){let Z=H(q,U.name);if(U.isDirectory()){let _=U.name;if(m(_))await p(Z,_,B,G);else if(J){let A=Q?`${Q}${K}${U.name}`:U.name;await P(Z,B,G,J,K,A)}}else if(U.isFile()){let _=w(U.name);if(G.includes(_)){let A=V(U.name,_);if(!B[A])B[A]={};let T=await N(Z);if(Q)u(B[A],Q,T,K);else B[A]=R(B[A],T)}}}}async function p(q,B,G,J){if(!G[B])G[B]={};let K=S(q,{withFileTypes:!0});for(let Q of K){if(!Q.isFile())continue;let X=w(Q.name);if(!J.includes(X))continue;let U=H(q,Q.name),Z=V(Q.name,X),_=await N(U);if(Z===B)G[B]=R(G[B],_);else G[B][Z]=_}}async function N(q){let B=w(q).toLowerCase(),G=await k(q,"utf8");switch(B){case".json":try{return JSON.parse(G)}catch{throw Error(`Invalid JSON in translation file: ${q}`)}case".yaml":case".yml":return d(G);case".ts":case".js":{let J=await import(q);return J.default||J}default:throw Error(`Unsupported file type: ${B}`)}}async function g(q,B){let G=await N(B);return z(q,G),G}function d(q){try{let B=Bun.YAML.parse(q);if(!B||typeof B!=="object"||Array.isArray(B))throw Error("YAML content must be an object at the root level");return B}catch(B){let G=B instanceof Error?B.message:"Unknown YAML parse error";throw Error(`Invalid YAML translation file: ${G}`)}}function m(q){return/^[a-z]{2}(?:-[A-Z]{2})?(?:-[A-Za-z]+)?$/i.test(q)}function u(q,B,G,J){let K=B.split(J),Q=q;for(let U=0;U<K.length-1;U++){let Z=K[U];if(!Z)continue;if(!Q[Z]||typeof Q[Z]==="string")Q[Z]={};Q=Q[Z]}let X=K[K.length-1];if(X)Q[X]=G}function R(q,B){let G={...q};for(let J of Object.keys(B)){let K=B[J];if(K===void 0)continue;let Q=G[J];if(typeof K==="object"&&K!==null&&typeof Q==="object"&&Q!==null)G[J]=R(Q,K);else G[J]=K}return G}function Iq(q,B={}){return{load:()=>y({directory:q,...B}),loadLocale:(G,J)=>g(G,H(q,J))}}async function wq(q){let{loadTranslations:B}=await import("@stacksjs/ts-i18n"),G=await B(q);return Y(G),G}var Nq={en:{code:"en",name:"English",nativeName:"English",direction:"ltr"},"en-US":{code:"en-US",name:"English (US)",nativeName:"English (US)",direction:"ltr",region:"US"},"en-GB":{code:"en-GB",name:"English (UK)",nativeName:"English (UK)",direction:"ltr",region:"GB"},es:{code:"es",name:"Spanish",nativeName:"Espa\xF1ol",direction:"ltr"},fr:{code:"fr",name:"French",nativeName:"Fran\xE7ais",direction:"ltr"},de:{code:"de",name:"German",nativeName:"Deutsch",direction:"ltr"},it:{code:"it",name:"Italian",nativeName:"Italiano",direction:"ltr"},pt:{code:"pt",name:"Portuguese",nativeName:"Portugu\xEAs",direction:"ltr"},"pt-BR":{code:"pt-BR",name:"Portuguese (Brazil)",nativeName:"Portugu\xEAs (Brasil)",direction:"ltr",region:"BR"},zh:{code:"zh",name:"Chinese",nativeName:"\u4E2D\u6587",direction:"ltr"},"zh-CN":{code:"zh-CN",name:"Chinese (Simplified)",nativeName:"\u7B80\u4F53\u4E2D\u6587",direction:"ltr",region:"CN"},"zh-TW":{code:"zh-TW",name:"Chinese (Traditional)",nativeName:"\u7E41\u9AD4\u4E2D\u6587",direction:"ltr",region:"TW"},ja:{code:"ja",name:"Japanese",nativeName:"\u65E5\u672C\u8A9E",direction:"ltr"},ko:{code:"ko",name:"Korean",nativeName:"\uD55C\uAD6D\uC5B4",direction:"ltr"},ar:{code:"ar",name:"Arabic",nativeName:"\u0627\u0644\u0639\u0631\u0628\u064A\u0629",direction:"rtl"},he:{code:"he",name:"Hebrew",nativeName:"\u05E2\u05D1\u05E8\u05D9\u05EA",direction:"rtl"},ru:{code:"ru",name:"Russian",nativeName:"\u0420\u0443\u0441\u0441\u043A\u0438\u0439",direction:"ltr"},nl:{code:"nl",name:"Dutch",nativeName:"Nederlands",direction:"ltr"},pl:{code:"pl",name:"Polish",nativeName:"Polski",direction:"ltr"},tr:{code:"tr",name:"Turkish",nativeName:"T\xFCrk\xE7e",direction:"ltr"},vi:{code:"vi",name:"Vietnamese",nativeName:"Ti\u1EBFng Vi\u1EC7t",direction:"ltr"},th:{code:"th",name:"Thai",nativeName:"\u0E44\u0E17\u0E22",direction:"ltr"},hi:{code:"hi",name:"Hindi",nativeName:"\u0939\u093F\u0928\u094D\u0926\u0940",direction:"ltr"}};export{bq as writeI18nOutputs,sq as useI18n,kq as trans,pq as tm,yq as te,fq as tc,Lq as t,GB as stripLocalePrefix,Zq as sortStrings,gq as setLocale,l as setFallbackLocale,r as selectPluralForm,Jq as selectPlural,lq as resolveRequestLocale,c as parsePluralForms,BB as localizePath,Pq as loadTranslationsFromDisk,uq as loadTranslations,g as loadLocale,wq as loadFromTsI18n,y as loadFromDirectory,N as loadFile,_q as isRTL,cq as hasTranslation,s as hasPluralRule,v as getTextDirection,n as getSupportedPluralLocales,Qq as getRegionName,D as getPluralRule,M as getPluralCategory,dq as getLocale,Kq as getLanguageName,I as getDisplayName,Uq as getCurrencyName,iq as getAvailableLocales,Mq as generateI18nTypesFromModule,xq as generateI18nTypes,Dq as generateI18nSampleConfig,Bq as formatUnit,QB as formatTime,$B as formatRelativeTime,EB as formatPlural,_B as formatPercent,XB as formatNumber,AB as formatList,UB as formatDateTime,KB as formatDate,ZB as formatCurrency,Gq as formatBytes,oq as ensureLocalesLoaded,hq as createSimpleTranslator,qB as createLocaleSwitchResponse,Iq as createLoader,nq as createI18n,a as configure,Xq as compareStrings,aq as applyRequestLocale,mq as addTranslations,t as addPluralRule,Nq as LOCALE_INFO,rq as I18n};
package/dist/loader.d.ts DELETED
@@ -1,52 +0,0 @@
1
- import type { TranslationMessages, Translations } from './types';
2
- /**
3
- * Load translations from a directory
4
- */
5
- export declare function loadFromDirectory(options: LoaderOptions): Promise<Translations>;
6
- /**
7
- * Load a single translation file
8
- */
9
- export declare function loadFile(filePath: string): Promise<TranslationMessages>;
10
- /**
11
- * Load a single locale from a file or directory
12
- */
13
- export declare function loadLocale(locale: string, path: string): Promise<TranslationMessages>;
14
- /**
15
- * Create a translation loader for a specific directory
16
- */
17
- export declare function createLoader(directory: string, options?: Partial<Omit<LoaderOptions, 'directory'>>): {
18
- load: () => unknown;
19
- loadLocale: (locale: string, filename: string) => unknown
20
- };
21
- /**
22
- * Load translations via `@stacksjs/ts-i18n` and register them with the
23
- * global translator. This is the recommended path for new projects —
24
- * it gets you:
25
- *
26
- * - Per-locale subdirectory namespacing (en/auth.yaml → en.auth.*)
27
- * - First-class .ts/.json/.yaml support with consistent error
28
- * messages
29
- * - Optional `.d.ts` codegen via `generateI18nTypes()` so message
30
- * keys autocomplete in `t('…')` calls
31
- *
32
- * The legacy `loadFromDirectory()` remains for projects that depend
33
- * on its specific behavior; new code should prefer this entry.
34
- *
35
- * @example
36
- * ```ts
37
- * await loadFromTsI18n({
38
- * translationsDir: path.userI18nPath(),
39
- * defaultLocale: 'en',
40
- * fallbackLocale: 'en',
41
- * sources: ['yaml', 'ts', 'json'],
42
- * optional: true,
43
- * })
44
- * ```
45
- */
46
- export declare function loadFromTsI18n(config: import('@stacksjs/ts-i18n').I18nConfig): Promise<Translations>;
47
- export declare interface LoaderOptions {
48
- directory: string
49
- extensions?: string[]
50
- recursive?: boolean
51
- namespaceSeparator?: string
52
- }
@@ -1,16 +0,0 @@
1
- export declare function stripLocalePrefix(path: string, locales: string[]): { locale: string | null, path: string };
2
- export declare function localizePath(path: string, locale: string, defaultLocale: string): string;
3
- /**
4
- * Build a redirect Response that sets the `locale` cookie and sends the
5
- * visitor to the equivalent path in the requested locale (STX-style).
6
- */
7
- export declare function createLocaleSwitchResponse(request: Request, localeCode: string, config: LocaleSwitchConfig): Response;
8
- /**
9
- * Locale switch redirect — mirrors STX `buildLangPickerScript` path logic
10
- * (`/<code>/…` prefixes) so cookie-based fallbacks and `/locale/{code}`
11
- * redirects stay consistent with stx-serve i18n routing.
12
- */
13
- export declare interface LocaleSwitchConfig {
14
- locales: string[]
15
- defaultLocale: string
16
- }
@@ -1,42 +0,0 @@
1
- /**
2
- * Get the plural category for a number in a given locale
3
- */
4
- export declare function getPluralCategory(n: number, locale: string): PluralCategory;
5
- /**
6
- * Get the plural rule function for a locale
7
- */
8
- export declare function getPluralRule(locale: string): PluralRule;
9
- /**
10
- * Parse a plural string into its forms
11
- *
12
- * Supports formats:
13
- * - "one | other" (simple)
14
- * - "zero | one | other" (with zero)
15
- * - "{0} item | {0} items" (with placeholders)
16
- * - "no items | one item | {n} items" (with special forms)
17
- */
18
- export declare function parsePluralForms(str: string, separator?: string): Map<PluralCategory, string>;
19
- /**
20
- * Select the appropriate plural form for a count
21
- */
22
- export declare function selectPluralForm(forms: Map<PluralCategory, string>, count: number, locale: string): string;
23
- /**
24
- * Get all supported locales for pluralization
25
- */
26
- export declare function getSupportedPluralLocales(): string[];
27
- /**
28
- * Check if a locale has custom plural rules
29
- */
30
- export declare function hasPluralRule(locale: string): boolean;
31
- /**
32
- * Add a custom plural rule for a locale
33
- */
34
- export declare function addPluralRule(locale: string, rule: PluralRule): void;
35
- /**
36
- * Pluralization Rules
37
- *
38
- * Implements CLDR plural rules for various languages.
39
- * @see https://cldr.unicode.org/index/cldr-spec/plural-rules
40
- */
41
- export type PluralCategory = 'zero' | 'one' | 'two' | 'few' | 'many' | 'other';
42
- export type PluralRule = (_n: number) => PluralCategory;
@@ -1,79 +0,0 @@
1
- import type { I18nConfig, I18nInstance, InterpolationValues, TranslationMessages, Translations } from './types';
2
- /**
3
- * Set the current locale
4
- */
5
- export declare function setLocale(locale: string): void;
6
- /**
7
- * Get the current locale
8
- */
9
- export declare function getLocale(): string;
10
- /**
11
- * Set the fallback locale
12
- */
13
- export declare function setFallbackLocale(locale: string): void;
14
- /**
15
- * Get available locales
16
- */
17
- export declare function getAvailableLocales(): string[];
18
- /**
19
- * Add translations for a locale
20
- */
21
- export declare function addTranslations(locale: string, messages: TranslationMessages): void;
22
- /**
23
- * Load translations (alias for addTranslations for multiple locales)
24
- */
25
- export declare function loadTranslations(messages: Translations): void;
26
- /**
27
- * Check if a translation exists
28
- */
29
- export declare function hasTranslation(key: string, locale?: string): boolean;
30
- /**
31
- * Translate a key
32
- */
33
- export declare function t(key: string, values?: InterpolationValues, locale?: string): string;
34
- /**
35
- * Translate with pluralization
36
- */
37
- export declare function tc(key: string, count: number, values?: InterpolationValues, locale?: string): string;
38
- /**
39
- * Check if translation exists
40
- */
41
- export declare function te(key: string, locale?: string): boolean;
42
- /**
43
- * Get translation message object
44
- */
45
- export declare function tm(key: string, locale?: string): TranslationMessages | string | undefined;
46
- /**
47
- * Create a new i18n instance
48
- */
49
- export declare function createI18n(options?: Partial<I18nConfig>): I18n;
50
- /**
51
- * Use i18n composable (for Vue-like usage)
52
- */
53
- export declare function useI18n(options?: Partial<I18nConfig>): I18nInstance;
54
- /**
55
- * Configure the global i18n instance
56
- */
57
- export declare function configure(options: Partial<I18nConfig>): void;
58
- /**
59
- * Alias for t()
60
- */
61
- export declare const trans: unknown;
62
- /**
63
- * I18n class for creating isolated instances
64
- */
65
- export declare class I18n implements I18nInstance {
66
- constructor(options?: Partial<I18nConfig>);
67
- get locale(): string;
68
- set locale(value: string);
69
- get fallbackLocale(): string;
70
- get availableLocales(): string[];
71
- t: unknown;
72
- tc: unknown;
73
- te: unknown;
74
- tm: unknown;
75
- setLocale: unknown;
76
- addTranslations: unknown;
77
- d: unknown;
78
- n: unknown;
79
- }
package/dist/types.d.ts DELETED
@@ -1,213 +0,0 @@
1
- /**
2
- * Common locales with metadata
3
- * @defaultValue
4
- * ```ts
5
- * {
6
- * en: { code: 'en', name: 'English', nativeName: 'English', direction: 'ltr' },
7
- * 'en-US': {
8
- * code: 'en-US',
9
- * name: 'English (US)',
10
- * nativeName: 'English (US)',
11
- * direction: 'ltr',
12
- * region: 'US'
13
- * },
14
- * 'en-GB': {
15
- * code: 'en-GB',
16
- * name: 'English (UK)',
17
- * nativeName: 'English (UK)',
18
- * direction: 'ltr',
19
- * region: 'GB'
20
- * },
21
- * es: { code: 'es', name: 'Spanish', nativeName: 'Espa\u00f1ol', direction: 'ltr' },
22
- * fr: { code: 'fr', name: 'French', nativeName: 'Fran\u00e7ais', direction: 'ltr' },
23
- * de: { code: 'de', name: 'German', nativeName: 'Deutsch', direction: 'ltr' },
24
- * it: { code: 'it', name: 'Italian', nativeName: 'Italiano', direction: 'ltr' },
25
- * pt: {
26
- * code: 'pt',
27
- * name: 'Portuguese',
28
- * nativeName: 'Portugu\u00eas',
29
- * direction: 'ltr'
30
- * },
31
- * 'pt-BR': {
32
- * code: 'pt-BR',
33
- * name: 'Portuguese (Brazil)',
34
- * nativeName: 'Portugu\u00eas (Brasil)',
35
- * direction: 'ltr',
36
- * region: 'BR'
37
- * },
38
- * zh: { code: 'zh', name: 'Chinese', nativeName: '\u4e2d\u6587', direction: 'ltr' },
39
- * 'zh-CN': {
40
- * code: 'zh-CN',
41
- * name: 'Chinese (Simplified)',
42
- * nativeName: '\u7b80\u4f53\u4e2d\u6587',
43
- * direction: 'ltr',
44
- * region: 'CN'
45
- * },
46
- * 'zh-TW': {
47
- * code: 'zh-TW',
48
- * name: 'Chinese (Traditional)',
49
- * nativeName: '\u7e41\u9ad4\u4e2d\u6587',
50
- * direction: 'ltr',
51
- * region: 'TW'
52
- * },
53
- * ja: {
54
- * code: 'ja',
55
- * name: 'Japanese',
56
- * nativeName: '\u65e5\u672c\u8a9e',
57
- * direction: 'ltr'
58
- * },
59
- * ko: {
60
- * code: 'ko',
61
- * name: 'Korean',
62
- * nativeName: '\ud55c\uad6d\uc5b4',
63
- * direction: 'ltr'
64
- * },
65
- * ar: {
66
- * code: 'ar',
67
- * name: 'Arabic',
68
- * nativeName: '\u0627\u0644\u0639\u0631\u0628\u064a\u0629',
69
- * direction: 'rtl'
70
- * },
71
- * he: {
72
- * code: 'he',
73
- * name: 'Hebrew',
74
- * nativeName: '\u05e2\u05d1\u05e8\u05d9\u05ea',
75
- * direction: 'rtl'
76
- * },
77
- * ru: {
78
- * code: 'ru',
79
- * name: 'Russian',
80
- * nativeName: '\u0420\u0443\u0441\u0441\u043a\u0438\u0439',
81
- * direction: 'ltr'
82
- * },
83
- * nl: { code: 'nl', name: 'Dutch', nativeName: 'Nederlands', direction: 'ltr' },
84
- * pl: { code: 'pl', name: 'Polish', nativeName: 'Polski', direction: 'ltr' },
85
- * tr: {
86
- * code: 'tr',
87
- * name: 'Turkish',
88
- * nativeName: 'T\u00fcrk\u00e7e',
89
- * direction: 'ltr'
90
- * },
91
- * vi: {
92
- * code: 'vi',
93
- * name: 'Vietnamese',
94
- * nativeName: 'Ti\u1ebfng Vi\u1ec7t',
95
- * direction: 'ltr'
96
- * },
97
- * th: { code: 'th', name: 'Thai', nativeName: '\u0e44\u0e17\u0e22', direction: 'ltr' },
98
- * hi: {
99
- * code: 'hi',
100
- * name: 'Hindi',
101
- * nativeName: '\u0939\u093f\u0928\u094d\u0926\u0940',
102
- * direction: 'ltr'
103
- * }
104
- * }
105
- * ```
106
- */
107
- export declare const LOCALE_INFO: Record<string, LocaleInfo>;
108
- /**
109
- * Plural forms for a translation
110
- */
111
- export declare interface PluralForms {
112
- zero?: string
113
- one: string
114
- two?: string
115
- few?: string
116
- many?: string
117
- other: string
118
- }
119
- /**
120
- * i18n configuration options
121
- */
122
- export declare interface I18nConfig {
123
- locale: string
124
- fallbackLocale: string
125
- availableLocales?: string[]
126
- messages?: Translations
127
- missingHandler?: (locale: string, key: string) => string | undefined
128
- warnMissing?: boolean
129
- escapeValues?: boolean
130
- keySeparator?: string
131
- pluralSeparator?: string
132
- dateTimeFormats?: DateTimeFormats
133
- numberFormats?: NumberFormats
134
- }
135
- /**
136
- * i18n instance interface
137
- */
138
- export declare interface I18nInstance {
139
- locale: string
140
- fallbackLocale: string
141
- availableLocales: string[]
142
- t: TranslateFunction
143
- tc: TranslatePluralFunction
144
- te: (key: string, locale?: string) => boolean
145
- tm: (key: string, locale?: string) => TranslationMessages | string | undefined
146
- setLocale: (locale: string) => void
147
- addTranslations: (locale: string, messages: TranslationMessages) => void
148
- d: (value: Date | number, format?: string) => string
149
- n: (value: number, format?: string) => string
150
- }
151
- /**
152
- * Locale metadata
153
- */
154
- export declare interface LocaleInfo {
155
- code: string
156
- name: string
157
- nativeName: string
158
- direction: 'ltr' | 'rtl'
159
- region?: string
160
- script?: string
161
- }
162
- /**
163
- * i18n Type Definitions
164
- */
165
- /**
166
- * Translation messages - can be nested objects or strings
167
- */
168
- export type TranslationMessages = {
169
- [key: string]: string | TranslationMessages
170
- }
171
- /**
172
- * All translations keyed by locale
173
- */
174
- export type Translations = {
175
- [locale: string]: TranslationMessages
176
- }
177
- /**
178
- * Interpolation values for translations
179
- */
180
- export type InterpolationValues = Record<string, string | number | boolean | null | undefined>;
181
- /**
182
- * Date/time format configurations per locale
183
- */
184
- export type DateTimeFormats = {
185
- [locale: string]: {
186
- [formatName: string]: Intl.DateTimeFormatOptions
187
- }
188
- }
189
- /**
190
- * Number format configurations per locale
191
- */
192
- export type NumberFormats = {
193
- [locale: string]: {
194
- [formatName: string]: Intl.NumberFormatOptions
195
- }
196
- }
197
- /**
198
- * Translation function
199
- */
200
- export type TranslateFunction = (
201
- key: string,
202
- values?: InterpolationValues,
203
- locale?: string,
204
- ) => string;
205
- /**
206
- * Plural translation function
207
- */
208
- export type TranslatePluralFunction = (
209
- key: string,
210
- count: number,
211
- values?: InterpolationValues,
212
- locale?: string,
213
- ) => string;