@stacksjs/i18n 0.72.57 → 0.72.61

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.
@@ -1 +1 @@
1
- import{parsePluralForms,selectPluralForm,getPluralCategory}from"./pluralization";const defaultConfig={locale:"en",fallbackLocale:"en",availableLocales:["en"],messages:{},warnMissing:!0,escapeValues:!1,keySeparator:".",pluralSeparator:"|"};let currentLocale="en",fallbackLocale="en";const translations={};let config={...defaultConfig};export class I18n{_locale;_fallbackLocale;_messages;_config;constructor(options={}){this._config={...defaultConfig,...options};this._locale=this._config.locale;this._fallbackLocale=this._config.fallbackLocale;this._messages=this._config.messages||{}}get locale(){return this._locale}set locale(value){this._locale=value}get fallbackLocale(){return this._fallbackLocale}get availableLocales(){return Object.keys(this._messages)}t=(key,values,locale)=>{return this.translate(key,values,locale)};tc=(key,count,values,locale)=>{return this.translatePlural(key,count,values,locale)};te=(key,locale)=>{return this.hasTranslation(key,locale)};tm=(key,locale)=>{return this.getMessage(key,locale??this.locale)};setLocale=(locale)=>{this._locale=locale};addTranslations=(locale,messages)=>{if(!this._messages[locale])this._messages[locale]={};this._messages[locale]=deepMerge(this._messages[locale],messages)};d=(value,format)=>{const date=typeof value==="number"?new Date(value):value,options=this._config.dateTimeFormats?.[this._locale]?.[format||"short"]||{};return new Intl.DateTimeFormat(this._locale,options).format(date)};n=(value,format)=>{const options=this._config.numberFormats?.[this._locale]?.[format||"decimal"]||{};return new Intl.NumberFormat(this._locale,options).format(value)};translate(key,values,locale){const targetLocale=locale||this._locale;let message=this.getMessage(key,targetLocale);if(message===void 0){const dash=targetLocale.indexOf("-");if(dash>0){const langOnly=targetLocale.slice(0,dash);if(langOnly!==this._fallbackLocale)message=this.getMessage(key,langOnly)}}if(message===void 0&&targetLocale!==this._fallbackLocale)message=this.getMessage(key,this._fallbackLocale);if(message===void 0){if(this._config.warnMissing)console.warn(`[i18n] Missing translation: "${key}" for locale "${targetLocale}"`);if(this._config.missingHandler){const result=this._config.missingHandler(targetLocale,key);if(result!==void 0)return result}return key}if(typeof message!=="string")return key;return this.interpolate(message,values)}translatePlural(key,count,values,locale){const targetLocale=locale||this._locale;let message=this.getMessage(key,targetLocale);if(message===void 0&&targetLocale!==this._fallbackLocale)message=this.getMessage(key,this._fallbackLocale);if(message===void 0||typeof message!=="string"){if(this._config.warnMissing)console.warn(`[i18n] Missing plural translation: "${key}" for locale "${targetLocale}"`);return key}const forms=parsePluralForms(message,this._config.pluralSeparator),selectedForm=selectPluralForm(forms,count,targetLocale),allValues={count,n:count,...values};return this.interpolate(selectedForm,allValues)}hasTranslation(key,locale){const targetLocale=locale||this._locale;return this.getMessage(key,targetLocale)!==void 0}getMessage(key,locale){const messages=this._messages[locale];if(!messages)return;const parts=key.split(this._config.keySeparator||".");let current=messages;for(const part of parts){if(current===void 0||typeof current==="string")return;current=current[part]}return current}interpolate(message,values){if(!values)return message;return message.replace(/\{(\w+)\}/g,(match,key)=>{const value=values[key];if(value===void 0||value===null)return match;const str=String(value);return this._config.escapeValues?escapeHtml(str):str})}}export function setLocale(locale){currentLocale=locale}export function getLocale(){return currentLocale}export function setFallbackLocale(locale){fallbackLocale=locale}export function getAvailableLocales(){return Object.keys(translations)}export function addTranslations(locale,messages){if(!translations[locale])translations[locale]={};translations[locale]=deepMerge(translations[locale],messages)}export function loadTranslations(messages){for(const[locale,localeMessages]of Object.entries(messages))addTranslations(locale,localeMessages)}export function hasTranslation(key,locale){return getMessage(key,locale||currentLocale)!==void 0}function getMessage(key,locale){const messages=translations[locale];if(!messages)return;const parts=key.split(config.keySeparator||".");let current=messages;for(const part of parts){if(current===void 0||typeof current==="string")return;current=current[part]}return current}function interpolate(message,values){if(!values)return message;return message.replace(/\{(\w+)\}/g,(match,key)=>{const value=values[key];if(value===void 0||value===null)return match;return String(value)})}export function t(key,values,locale){const targetLocale=locale||currentLocale;let message=getMessage(key,targetLocale);if(message===void 0&&targetLocale!==fallbackLocale)message=getMessage(key,fallbackLocale);if(message===void 0){if(config.warnMissing)console.warn(`[i18n] Missing translation: "${key}" for locale "${targetLocale}"`);return key}if(typeof message!=="string")return key;return interpolate(message,values)}export const trans=t;export function tc(key,count,values,locale){const targetLocale=locale||currentLocale;let message=getMessage(key,targetLocale);if(message===void 0&&targetLocale!==fallbackLocale)message=getMessage(key,fallbackLocale);if(message===void 0||typeof message!=="string")return key;const forms=parsePluralForms(message,config.pluralSeparator),selectedForm=selectPluralForm(forms,count,targetLocale),allValues={count,n:count,...values};return interpolate(selectedForm,allValues)}export function te(key,locale){return hasTranslation(key,locale)}export function tm(key,locale){return getMessage(key,locale||currentLocale)}export function createI18n(options={}){return new I18n(options)}export function useI18n(options={}){return createI18n(options)}export function configure(options){config={...config,...options};if(options.locale)currentLocale=options.locale;if(options.fallbackLocale)fallbackLocale=options.fallbackLocale;if(options.messages)loadTranslations(options.messages)}function deepMerge(target,source){const result={...target};for(const key of Object.keys(source)){const sourceValue=source[key],targetValue=result[key];if(typeof sourceValue==="object"&&sourceValue!==null&&typeof targetValue==="object"&&targetValue!==null)result[key]=deepMerge(targetValue,sourceValue);else if(sourceValue!==void 0)result[key]=sourceValue}return result}function escapeHtml(str){const htmlEscapes={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"};return str.replace(/[&<>"']/g,(char)=>htmlEscapes[char]||char)}
1
+ import{parsePluralForms,selectPluralForm}from"./pluralization";const defaultConfig={locale:"en",fallbackLocale:"en",availableLocales:["en"],messages:{},warnMissing:!0,escapeValues:!1,keySeparator:".",pluralSeparator:"|"};let currentLocale="en",fallbackLocale="en";const translations={};let config={...defaultConfig};export class I18n{_locale;_fallbackLocale;_messages;_config;constructor(options={}){this._config={...defaultConfig,...options};this._locale=this._config.locale;this._fallbackLocale=this._config.fallbackLocale;this._messages=this._config.messages||{}}get locale(){return this._locale}set locale(value){this._locale=value}get fallbackLocale(){return this._fallbackLocale}get availableLocales(){return Object.keys(this._messages)}t=(key,values,locale)=>{return this.translate(key,values,locale)};tc=(key,count,values,locale)=>{return this.translatePlural(key,count,values,locale)};te=(key,locale)=>{return this.hasTranslation(key,locale)};tm=(key,locale)=>{return this.getMessage(key,locale??this.locale)};setLocale=(locale)=>{this._locale=locale};addTranslations=(locale,messages)=>{if(!this._messages[locale])this._messages[locale]={};this._messages[locale]=deepMerge(this._messages[locale],messages)};d=(value,format)=>{const date=typeof value==="number"?new Date(value):value,options=this._config.dateTimeFormats?.[this._locale]?.[format||"short"]||{};return new Intl.DateTimeFormat(this._locale,options).format(date)};n=(value,format)=>{const options=this._config.numberFormats?.[this._locale]?.[format||"decimal"]||{};return new Intl.NumberFormat(this._locale,options).format(value)};translate(key,values,locale){const targetLocale=locale||this._locale;let message=this.getMessage(key,targetLocale);if(message===void 0){const dash=targetLocale.indexOf("-");if(dash>0){const langOnly=targetLocale.slice(0,dash);if(langOnly!==this._fallbackLocale)message=this.getMessage(key,langOnly)}}if(message===void 0&&targetLocale!==this._fallbackLocale)message=this.getMessage(key,this._fallbackLocale);if(message===void 0){if(this._config.warnMissing)console.warn(`[i18n] Missing translation: "${key}" for locale "${targetLocale}"`);if(this._config.missingHandler){const result=this._config.missingHandler(targetLocale,key);if(result!==void 0)return result}return key}if(typeof message!=="string")return key;return this.interpolate(message,values)}translatePlural(key,count,values,locale){const targetLocale=locale||this._locale;let message=this.getMessage(key,targetLocale);if(message===void 0&&targetLocale!==this._fallbackLocale)message=this.getMessage(key,this._fallbackLocale);if(message===void 0||typeof message!=="string"){if(this._config.warnMissing)console.warn(`[i18n] Missing plural translation: "${key}" for locale "${targetLocale}"`);return key}const forms=parsePluralForms(message,this._config.pluralSeparator),selectedForm=selectPluralForm(forms,count,targetLocale),allValues={count,n:count,...values};return this.interpolate(selectedForm,allValues)}hasTranslation(key,locale){const targetLocale=locale||this._locale;return this.getMessage(key,targetLocale)!==void 0}getMessage(key,locale){const messages=this._messages[locale];if(!messages)return;const parts=key.split(this._config.keySeparator||".");let current=messages;for(const part of parts){if(current===void 0||typeof current==="string")return;current=current[part]}return current}interpolate(message,values){if(!values)return message;return message.replace(/\{(\w+)\}/g,(match,key)=>{const value=values[key];if(value===void 0||value===null)return match;const str=String(value);return this._config.escapeValues?escapeHtml(str):str})}}export function setLocale(locale){currentLocale=locale}export function getLocale(){return currentLocale}export function setFallbackLocale(locale){fallbackLocale=locale}export function getAvailableLocales(){return Object.keys(translations)}export function addTranslations(locale,messages){if(!translations[locale])translations[locale]={};translations[locale]=deepMerge(translations[locale],messages)}export function loadTranslations(messages){for(const[locale,localeMessages]of Object.entries(messages))addTranslations(locale,localeMessages)}export function hasTranslation(key,locale){return getMessage(key,locale||currentLocale)!==void 0}function getMessage(key,locale){const messages=translations[locale];if(!messages)return;const parts=key.split(config.keySeparator||".");let current=messages;for(const part of parts){if(current===void 0||typeof current==="string")return;current=current[part]}return current}function interpolate(message,values){if(!values)return message;return message.replace(/\{(\w+)\}/g,(match,key)=>{const value=values[key];if(value===void 0||value===null)return match;return String(value)})}export function t(key,values,locale){const targetLocale=locale||currentLocale;let message=getMessage(key,targetLocale);if(message===void 0&&targetLocale!==fallbackLocale)message=getMessage(key,fallbackLocale);if(message===void 0){if(config.warnMissing)console.warn(`[i18n] Missing translation: "${key}" for locale "${targetLocale}"`);return key}if(typeof message!=="string")return key;return interpolate(message,values)}export const trans=t;export function tc(key,count,values,locale){const targetLocale=locale||currentLocale;let message=getMessage(key,targetLocale);if(message===void 0&&targetLocale!==fallbackLocale)message=getMessage(key,fallbackLocale);if(message===void 0||typeof message!=="string")return key;const forms=parsePluralForms(message,config.pluralSeparator),selectedForm=selectPluralForm(forms,count,targetLocale),allValues={count,n:count,...values};return interpolate(selectedForm,allValues)}export function te(key,locale){return hasTranslation(key,locale)}export function tm(key,locale){return getMessage(key,locale||currentLocale)}export function createI18n(options={}){return new I18n(options)}export function useI18n(options={}){return createI18n(options)}export function configure(options){config={...config,...options};if(options.locale)currentLocale=options.locale;if(options.fallbackLocale)fallbackLocale=options.fallbackLocale;if(options.messages)loadTranslations(options.messages)}function deepMerge(target,source){const result={...target};for(const key of Object.keys(source)){const sourceValue=source[key],targetValue=result[key];if(typeof sourceValue==="object"&&sourceValue!==null&&typeof targetValue==="object"&&targetValue!==null)result[key]=deepMerge(targetValue,sourceValue);else if(sourceValue!==void 0)result[key]=sourceValue}return result}function escapeHtml(str){const htmlEscapes={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"};return str.replace(/[&<>"']/g,(char)=>htmlEscapes[char]||char)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stacksjs/i18n",
3
- "version": "0.72.57",
3
+ "version": "0.72.61",
4
4
  "description": "Internationalization system for Stacks.js applications",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -39,7 +39,7 @@
39
39
  "@stacksjs/ts-i18n": "^0.1.9"
40
40
  },
41
41
  "devDependencies": {
42
- "@stacksjs/development": "0.72.57"
42
+ "@stacksjs/development": "0.72.61"
43
43
  },
44
44
  "publishConfig": {
45
45
  "exports": {