@translifycc/angular 0.1.3 β†’ 0.1.5

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translifycc-angular.mjs","sources":["../../src/translate.ts","../../src/translify-selector.component.ts","../../src/translify.module.ts","../../src/translifycc-angular.ts"],"sourcesContent":["export interface Language {\n code: string;\n name: string;\n nativeName: string;\n isRTL: boolean;\n}\n\nconst SKIP_TAGS = new Set([\n 'SCRIPT', 'STYLE', 'NOSCRIPT', 'IFRAME',\n 'CODE', 'PRE', 'SVG', 'MATH', 'INPUT', 'TEXTAREA',\n]);\n\nexport function getSavedLang(): string | null {\n return localStorage.getItem('translify_lang');\n}\n\nexport function saveLang(lang: string): void {\n localStorage.setItem('translify_lang', lang);\n}\n\nexport function clearSavedLang(): void {\n localStorage.removeItem('translify_lang');\n}\n\nexport function loadTranslationCache(lang: string): Map<string, string> {\n try {\n const stored = localStorage.getItem(`translify_cache_${lang}`);\n return stored ? new Map(Object.entries(JSON.parse(stored))) : new Map();\n } catch {\n return new Map();\n }\n}\n\nexport function saveTranslationCache(lang: string, cache: Map<string, string>): void {\n try {\n const obj: Record<string, string> = {};\n cache.forEach((v, k) => { obj[k] = v; });\n localStorage.setItem(`translify_cache_${lang}`, JSON.stringify(obj));\n } catch {}\n}\n\nexport function getTextNodes(root: Node): Text[] {\n const nodes: Text[] = [];\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {\n acceptNode(node: Node) {\n const text = (node as Text);\n if (!text.textContent?.trim()) return NodeFilter.FILTER_REJECT;\n if (SKIP_TAGS.has((text.parentElement?.tagName ?? ''))) return NodeFilter.FILTER_REJECT;\n if ((text.textContent?.trim().length ?? 0) > 5000) return NodeFilter.FILTER_REJECT;\n if (text.parentElement?.closest('[translate=\"no\"]')) return NodeFilter.FILTER_REJECT;\n return NodeFilter.FILTER_ACCEPT;\n },\n });\n let n: Node | null;\n while ((n = walker.nextNode())) nodes.push(n as Text);\n return nodes;\n}\n\nexport function collectNewTextNodes(node: Node, originalTexts: Map<Node, string>): Text[] {\n const nodes: Text[] = [];\n if (node.nodeType === Node.TEXT_NODE) {\n const t = node as Text;\n if (!originalTexts.has(t) && t.textContent?.trim()) nodes.push(t);\n } else if (node.nodeType === Node.ELEMENT_NODE) {\n const walker = document.createTreeWalker(node, NodeFilter.SHOW_TEXT);\n let n: Node | null;\n while ((n = walker.nextNode())) {\n const t = n as Text;\n if (\n !originalTexts.has(t) &&\n t.textContent?.trim() &&\n !SKIP_TAGS.has(t.parentElement?.tagName ?? '') &&\n !t.parentElement?.closest('[translate=\"no\"]')\n ) {\n nodes.push(t);\n }\n }\n }\n return nodes;\n}\n\nexport async function fetchLanguages(apiBase: string): Promise<Language[]> {\n const res = await fetch(`${apiBase}/translate/languages`);\n const json = await res.json();\n return json.data.languages;\n}\n\nexport async function callTranslateApi(\n apiBase: string,\n apiKey: string,\n domain: string,\n texts: string[],\n targetLang: string,\n): Promise<string[]> {\n const results: string[] = [];\n for (let i = 0; i < texts.length; i += 100) {\n const chunk = texts.slice(i, i + 100);\n const res = await fetch(`${apiBase}/translate`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': apiKey,\n 'x-domain': domain,\n },\n body: JSON.stringify({ texts: chunk, targetLanguage: targetLang, sourceLanguage: 'auto' }),\n });\n const json = await res.json();\n if (!json.success) throw new Error(json.message || 'Translation failed');\n results.push(...json.data.translations);\n }\n return results;\n}\n","import {\n Component,\n Input,\n OnInit,\n OnDestroy,\n NgZone,\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n} from '@angular/core';\nimport { NgIf, NgFor, NgClass } from '@angular/common';\nimport {\n Language,\n getSavedLang,\n saveLang,\n clearSavedLang,\n loadTranslationCache,\n saveTranslationCache,\n getTextNodes,\n collectNewTextNodes,\n fetchLanguages,\n callTranslateApi,\n} from './translate';\n\n@Component({\n selector: 'translify-selector',\n standalone: true,\n imports: [NgIf, NgFor, NgClass],\n changeDetection: ChangeDetectionStrategy.OnPush,\n styles: [`\n .translify-selector { position: relative; display: inline-block; }\n .translify-trigger {\n display: inline-flex; align-items: center; gap: 6px;\n padding: 8px 14px; border-radius: 8px; border: 1px solid #e5e7eb;\n background: #fff; cursor: pointer; font-size: 14px; color: #374151;\n transition: border-color 0.15s;\n }\n .translify-trigger:hover { border-color: #9ca3af; }\n .translify-trigger:disabled { opacity: 0.5; cursor: not-allowed; }\n .translify-trigger-chevron { font-size: 10px; transition: transform 0.2s; }\n .translify-trigger-chevron.open { transform: rotate(180deg); }\n .translify-dropdown {\n position: absolute; top: calc(100% + 6px); left: 0; z-index: 9999;\n background: #fff; border: 1px solid #e5e7eb; border-radius: 12px;\n min-width: 220px; max-height: 320px; overflow-y: auto;\n box-shadow: 0 8px 24px rgba(0,0,0,0.12); display: flex; flex-direction: column;\n }\n .translify-dropdown-header {\n padding: 10px 14px; font-size: 11px; font-weight: 700;\n color: #6b7280; text-transform: uppercase; letter-spacing: 0.06em;\n border-bottom: 1px solid #f3f4f6; flex-shrink: 0;\n }\n .translify-option {\n display: flex; align-items: center; gap: 8px;\n padding: 10px 14px; cursor: pointer; font-size: 14px;\n color: #111827; border: none; background: none; width: 100%; text-align: left;\n transition: background 0.1s;\n }\n .translify-option:hover { background: #f9fafb; }\n .translify-option.active { background: #eff6ff; color: #2563eb; font-weight: 600; }\n .translify-option-name { font-size: 12px; color: #9ca3af; margin-left: auto; }\n .translify-option-rtl {\n font-size: 10px; color: #9ca3af;\n background: #f3f4f6; padding: 2px 5px; border-radius: 4px;\n }\n .translify-restore {\n display: flex; align-items: center; gap: 6px;\n padding: 10px 14px; cursor: pointer; font-size: 13px; color: #ef4444;\n border: none; background: none; width: 100%; text-align: left;\n border-top: 1px solid #f3f4f6; flex-shrink: 0; transition: background 0.1s;\n }\n .translify-restore:hover { background: #fff5f5; }\n .translify-toast {\n position: fixed; bottom: 84px; right: 24px; z-index: 2147483647;\n background: #1e293b; color: #fff; padding: 10px 16px;\n border-radius: 10px; font-size: 13px; pointer-events: none;\n transition: opacity 0.3s ease, transform 0.3s ease;\n }\n .translify-overlay {\n position: fixed; inset: 0; z-index: 2147483646;\n background: rgba(255,255,255,0.85); backdrop-filter: blur(3px);\n display: flex; flex-direction: column;\n align-items: center; justify-content: center; gap: 14px;\n transition: opacity 0.35s ease;\n }\n .translify-overlay-spinner {\n width: 40px; height: 40px; border-radius: 50%;\n border: 3px solid #e5e7eb; border-top-color: #2563eb;\n animation: tlfy-spin 0.7s linear infinite;\n }\n @keyframes tlfy-spin { to { transform: rotate(360deg); } }\n .translify-overlay-title { font-size: 15px; font-weight: 600; color: #111827; text-align: center; }\n .translify-overlay-sub { font-size: 12px; color: #6b7280; margin-top: 4px; text-align: center; }\n `],\n template: `\n <div class=\"translify-selector\" (clickOutside)=\"isOpen = false\">\n <button\n class=\"translify-trigger\"\n [class]=\"classNames.trigger || ''\"\n (click)=\"isOpen = !isOpen\"\n [disabled]=\"loadingState !== 'idle' || languages.length === 0\"\n [attr.aria-expanded]=\"isOpen\"\n >\n <span>🌐</span>\n <span>{{ activeLangObj ? activeLangObj.nativeName : (labels.trigger || 'Translate') }}</span>\n <span class=\"translify-trigger-chevron\" [class.open]=\"isOpen\">β–Ύ</span>\n </button>\n\n <div *ngIf=\"isOpen\" class=\"translify-dropdown\" [class]=\"classNames.dropdown || ''\">\n <div class=\"translify-dropdown-header\">{{ labels.dropdownHeader || 'Select Language' }}</div>\n\n <button\n *ngFor=\"let lang of languages\"\n class=\"translify-option\"\n [class.active]=\"activeLang === lang.code\"\n (click)=\"handleSelect(lang.code)\"\n >\n <span>{{ lang.nativeName }}</span>\n <span class=\"translify-option-name\">{{ lang.name }}</span>\n <span *ngIf=\"lang.isRTL\" class=\"translify-option-rtl\">RTL</span>\n </button>\n\n <button *ngIf=\"activeLang\" class=\"translify-restore\" (click)=\"restore()\">\n ↩ {{ labels.restore || 'Show original' }}\n </button>\n </div>\n </div>\n\n <div\n *ngIf=\"loadingState === 'overlay'\"\n class=\"translify-overlay\"\n [style.opacity]=\"overlayVisible ? '1' : '0'\"\n >\n <div class=\"translify-overlay-spinner\"></div>\n <div>\n <div class=\"translify-overlay-title\">{{ labels.overlayTitle || 'Translating page…' }}</div>\n <div class=\"translify-overlay-sub\">{{ labels.overlaySub || 'First time only β€” instant on next visit.' }}</div>\n </div>\n </div>\n\n <div\n *ngIf=\"loadingState === 'toast'\"\n class=\"translify-toast\"\n [style.opacity]=\"toastVisible ? '1' : '0'\"\n [style.transform]=\"toastVisible ? 'translateY(0)' : 'translateY(8px)'\"\n >\n ⏳ Translating…\n </div>\n `,\n})\nexport class TranslifySelectorComponent implements OnInit, OnDestroy {\n @Input() apiKey!: string;\n @Input() apiBase = 'https://translify.cc';\n @Input() domain = window.location.hostname || 'localhost';\n @Input() classNames: {\n trigger?: string; dropdown?: string; dropdownHeader?: string;\n option?: string; optionActive?: string; optionNative?: string;\n optionName?: string; optionRtl?: string; restore?: string;\n overlay?: string; overlaySpinner?: string; overlayTitle?: string;\n overlaySub?: string; toast?: string;\n } = {};\n @Input() labels: {\n trigger?: string; dropdownHeader?: string; restore?: string;\n overlayTitle?: string; overlaySub?: string;\n } = {};\n\n languages: Language[] = [];\n activeLang: string | null = getSavedLang();\n isOpen = false;\n loadingState: 'idle' | 'overlay' | 'toast' = 'idle';\n overlayVisible = false;\n toastVisible = false;\n\n // All mutable translation state β€” no change detection needed\n private originalTexts = new Map<Node, string>();\n private translationCache = new Map<string, string>();\n private currentCacheLang: string | null = null;\n private isTranslating = false;\n private pendingNodes: Text[] = [];\n private observer: MutationObserver | null = null;\n private debounceTimer: any = null;\n private overlayTimer: any = null;\n\n constructor(private ngZone: NgZone, private cdr: ChangeDetectorRef) {}\n\n get activeLangObj(): Language | undefined {\n return this.languages.find((l) => l.code === this.activeLang);\n }\n\n async ngOnInit() {\n if (!this.apiKey) { console.error('[Translify] apiKey is required.'); return; }\n\n try {\n this.languages = await fetchLanguages(this.apiBase);\n this.cdr.markForCheck();\n } catch (e) {\n console.error('[Translify] Failed to fetch languages', e);\n return;\n }\n\n this.ngZone.runOutsideAngular(() => {\n this.startObserver();\n this.patchHistory();\n });\n\n if (this.activeLang && this.languages.length > 0) {\n await this.translate(this.activeLang);\n }\n }\n\n ngOnDestroy() {\n this.stopObserver();\n clearTimeout(this.overlayTimer);\n }\n\n // ── Cache helpers ───────────────────────────────────────────────────────────\n\n private ensureCacheLoaded(lang: string) {\n if (this.currentCacheLang === lang) return;\n this.translationCache = loadTranslationCache(lang);\n this.currentCacheLang = lang;\n }\n\n private applyCache(nodes: Text[]): Text[] {\n const uncached: Text[] = [];\n nodes.forEach((node) => {\n const src = this.originalTexts.get(node) ?? node.textContent ?? '';\n const hit = this.translationCache.get(src);\n if (hit !== undefined) {\n node.textContent = hit;\n } else {\n uncached.push(node);\n }\n });\n return uncached;\n }\n\n // ── Overlay / toast ─────────────────────────────────────────────────────────\n\n private showOverlay() {\n clearTimeout(this.overlayTimer);\n this.ngZone.run(() => {\n this.overlayVisible = false;\n this.loadingState = 'overlay';\n requestAnimationFrame(() => { this.overlayVisible = true; this.cdr.markForCheck(); });\n this.cdr.markForCheck();\n });\n }\n\n private hideOverlay() {\n this.overlayTimer = setTimeout(() => {\n this.ngZone.run(() => { this.overlayVisible = false; this.cdr.markForCheck(); });\n this.overlayTimer = setTimeout(() => {\n this.ngZone.run(() => { this.loadingState = 'idle'; this.cdr.markForCheck(); });\n }, 400);\n }, 600);\n }\n\n private showToast() {\n clearTimeout(this.overlayTimer);\n this.ngZone.run(() => {\n this.loadingState = 'toast';\n requestAnimationFrame(() => { this.toastVisible = true; this.cdr.markForCheck(); });\n this.cdr.markForCheck();\n });\n }\n\n private hideToast() {\n this.ngZone.run(() => {\n this.toastVisible = false;\n this.overlayTimer = setTimeout(() => {\n this.ngZone.run(() => { this.loadingState = 'idle'; this.cdr.markForCheck(); });\n }, 350);\n this.cdr.markForCheck();\n });\n }\n\n // ── flushNodes ──────────────────────────────────────────────────────────────\n\n private async flushNodes(nodes: Text[], targetLang: string) {\n if (!nodes.length) return;\n if (this.isTranslating) { this.pendingNodes.push(...nodes); return; }\n this.isTranslating = true;\n\n try {\n nodes.forEach((n) => {\n if (!this.originalTexts.has(n)) this.originalTexts.set(n, n.textContent ?? '');\n });\n const uncached = this.applyCache(nodes);\n if (uncached.length > 0) {\n const texts = uncached.map((n) => this.originalTexts.get(n)!);\n const translations = await callTranslateApi(this.apiBase, this.apiKey, this.domain, texts, targetLang);\n uncached.forEach((node, i) => {\n if (translations[i] !== undefined) {\n this.translationCache.set(this.originalTexts.get(node)!, translations[i]);\n node.textContent = translations[i];\n }\n });\n saveTranslationCache(targetLang, this.translationCache);\n }\n } catch (e) {\n console.error('[Translify] Dynamic translation error', e);\n } finally {\n this.isTranslating = false;\n if (this.pendingNodes.length > 0) {\n const next = this.pendingNodes.splice(0);\n this.flushNodes(next, targetLang);\n }\n }\n }\n\n // ── MutationObserver ────────────────────────────────────────────────────────\n\n private startObserver() {\n if (this.observer) return;\n\n this.observer = new MutationObserver((mutations) => {\n if (!this.activeLang) return;\n const targetLang = this.activeLang;\n\n const newNodes: Text[] = [];\n mutations.forEach((mutation) => {\n if (mutation.type !== 'childList') return;\n mutation.addedNodes.forEach((node) => {\n newNodes.push(...collectNewTextNodes(node, this.originalTexts));\n });\n });\n if (!newNodes.length) return;\n\n const uncached: Text[] = [];\n newNodes.forEach((node) => {\n const src = node.textContent ?? '';\n const hit = this.translationCache.get(src);\n if (hit !== undefined) {\n this.originalTexts.set(node, src);\n node.textContent = hit;\n } else {\n uncached.push(node);\n }\n });\n if (!uncached.length) return;\n\n this.pendingNodes.push(...uncached);\n if (!this.isTranslating) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = setTimeout(() => {\n const toFlush = this.pendingNodes.splice(0);\n this.flushNodes(toFlush, targetLang);\n }, 50);\n }\n });\n\n this.observer.observe(document.body, { childList: true, subtree: true });\n }\n\n private stopObserver() {\n if (this.observer) { this.observer.disconnect(); this.observer = null; }\n clearTimeout(this.debounceTimer);\n }\n\n // ── SPA route change detection ──────────────────────────────────────────────\n\n private patchHistory() {\n const orig = history.pushState.bind(history);\n const self = this;\n history.pushState = function(state: unknown, unused: string, url?: string | URL | null) {\n orig(state, unused, url);\n self.onRouteChange();\n };\n window.addEventListener('popstate', () => this.onRouteChange());\n }\n\n private onRouteChange() {\n if (!this.activeLang) return;\n const targetLang = this.activeLang;\n setTimeout(() => {\n const nodes = getTextNodes(document.body).filter((n) => !this.originalTexts.has(n));\n if (!nodes.length) return;\n this.pendingNodes.push(...nodes);\n if (!this.isTranslating) {\n const toFlush = this.pendingNodes.splice(0);\n this.flushNodes(toFlush, targetLang);\n }\n }, 100);\n }\n\n // ── Main translate ──────────────────────────────────────────────────────────\n\n async translate(targetLang: string) {\n if (this.isTranslating) return;\n this.isTranslating = true;\n\n try {\n this.ensureCacheLoaded(targetLang);\n const isFirstEver = this.translationCache.size === 0;\n\n if (this.originalTexts.size > 0) {\n this.originalTexts.forEach((text, node) => { node.textContent = text; });\n }\n\n const nodes = getTextNodes(document.body);\n if (!nodes.length) return;\n\n nodes.forEach((node) => {\n if (!this.originalTexts.has(node)) this.originalTexts.set(node, node.textContent ?? '');\n });\n\n const uncached = this.applyCache(nodes);\n\n const lang = this.languages.find((l) => l.code === targetLang);\n document.documentElement.setAttribute('dir', lang?.isRTL ? 'rtl' : 'ltr');\n\n saveLang(targetLang);\n this.ngZone.run(() => { this.activeLang = targetLang; this.cdr.markForCheck(); });\n\n if (uncached.length > 0) {\n if (isFirstEver) this.showOverlay(); else this.showToast();\n\n const texts = uncached.map((n) => this.originalTexts.get(n)!);\n const translations = await callTranslateApi(this.apiBase, this.apiKey, this.domain, texts, targetLang);\n\n uncached.forEach((node, i) => {\n if (translations[i] !== undefined) {\n this.translationCache.set(this.originalTexts.get(node)!, translations[i]);\n node.textContent = translations[i];\n }\n });\n\n saveTranslationCache(targetLang, this.translationCache);\n if (isFirstEver) this.hideOverlay(); else this.hideToast();\n }\n } catch (e) {\n console.error('[Translify] Translation error', e);\n this.hideOverlay(); this.hideToast();\n } finally {\n this.isTranslating = false;\n if (this.pendingNodes.length > 0) {\n const next = this.pendingNodes.splice(0);\n this.flushNodes(next, this.activeLang!);\n }\n }\n }\n\n // ── Restore ─────────────────────────────────────────────────────────────────\n\n restore() {\n this.stopObserver();\n this.originalTexts.forEach((text, node) => { node.textContent = text; });\n this.originalTexts.clear();\n document.documentElement.setAttribute('dir', 'ltr');\n clearSavedLang();\n this.activeLang = null;\n this.isOpen = false;\n this.cdr.markForCheck();\n this.ngZone.runOutsideAngular(() => this.startObserver());\n }\n\n // ── UI handlers ─────────────────────────────────────────────────────────────\n\n handleSelect(langCode: string) {\n this.isOpen = false;\n this.translate(langCode);\n }\n}\n","import { NgModule } from '@angular/core';\nimport { TranslifySelectorComponent } from './translify-selector.component';\n\n// For NgModule-based apps (Angular 15+)\n// Standalone component apps can import TranslifySelectorComponent directly\n@NgModule({\n imports: [TranslifySelectorComponent],\n exports: [TranslifySelectorComponent],\n})\nexport class TranslifyModule {}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,9 +1,19 @@
1
1
  {
2
2
  "name": "@translifycc/angular",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Angular language selector component for Translify",
5
- "main": "dist/index.js",
5
+ "main": "dist/fesm2022/translifycc-angular.mjs",
6
+ "module": "fesm2022/translifycc-angular.mjs",
6
7
  "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "default": "./fesm2022/translifycc-angular.mjs",
11
+ "types": "./types/translifycc-angular.d.ts"
12
+ },
13
+ "./package.json": {
14
+ "default": "./package.json"
15
+ }
16
+ },
7
17
  "peerDependencies": {
8
18
  "@angular/common": ">=15.0.0",
9
19
  "@angular/core": ">=15.0.0"
@@ -15,9 +25,9 @@
15
25
  "angular"
16
26
  ],
17
27
  "license": "MIT",
18
- "devDependencies": {
19
- "@angular/common": "^15.2.10",
20
- "@angular/core": "^15.2.10",
21
- "typescript": "^5.9.3"
28
+ "typings": "types/translifycc-angular.d.ts",
29
+ "sideEffects": false,
30
+ "dependencies": {
31
+ "tslib": "^2.3.0"
22
32
  }
23
- }
33
+ }
@@ -1,6 +1,14 @@
1
+ import * as i0 from '@angular/core';
1
2
  import { OnInit, OnDestroy, NgZone, ChangeDetectorRef } from '@angular/core';
2
- import { Language } from './translate';
3
- export declare class TranslifySelectorComponent implements OnInit, OnDestroy {
3
+
4
+ interface Language {
5
+ code: string;
6
+ name: string;
7
+ nativeName: string;
8
+ isRTL: boolean;
9
+ }
10
+
11
+ declare class TranslifySelectorComponent implements OnInit, OnDestroy {
4
12
  private ngZone;
5
13
  private cdr;
6
14
  apiKey: string;
@@ -61,4 +69,15 @@ export declare class TranslifySelectorComponent implements OnInit, OnDestroy {
61
69
  translate(targetLang: string): Promise<void>;
62
70
  restore(): void;
63
71
  handleSelect(langCode: string): void;
72
+ static Ι΅fac: i0.Ι΅Ι΅FactoryDeclaration<TranslifySelectorComponent, never>;
73
+ static Ι΅cmp: i0.Ι΅Ι΅ComponentDeclaration<TranslifySelectorComponent, "translify-selector", never, { "apiKey": { "alias": "apiKey"; "required": false; }; "apiBase": { "alias": "apiBase"; "required": false; }; "domain": { "alias": "domain"; "required": false; }; "classNames": { "alias": "classNames"; "required": false; }; "labels": { "alias": "labels"; "required": false; }; }, {}, never, never, true, never>;
74
+ }
75
+
76
+ declare class TranslifyModule {
77
+ static Ι΅fac: i0.Ι΅Ι΅FactoryDeclaration<TranslifyModule, never>;
78
+ static Ι΅mod: i0.Ι΅Ι΅NgModuleDeclaration<TranslifyModule, never, [typeof TranslifySelectorComponent], [typeof TranslifySelectorComponent]>;
79
+ static Ι΅inj: i0.Ι΅Ι΅InjectorDeclaration<TranslifyModule>;
64
80
  }
81
+
82
+ export { TranslifyModule, TranslifySelectorComponent };
83
+ export type { Language };
package/dist/index.d.ts DELETED
@@ -1,3 +0,0 @@
1
- export { TranslifySelectorComponent } from './translify-selector.component';
2
- export { TranslifyModule } from './translify.module';
3
- export type { Language } from './translate';
package/dist/index.js DELETED
@@ -1,2 +0,0 @@
1
- export { TranslifySelectorComponent } from './translify-selector.component';
2
- export { TranslifyModule } from './translify.module';
@@ -1,15 +0,0 @@
1
- export interface Language {
2
- code: string;
3
- name: string;
4
- nativeName: string;
5
- isRTL: boolean;
6
- }
7
- export declare function getSavedLang(): string | null;
8
- export declare function saveLang(lang: string): void;
9
- export declare function clearSavedLang(): void;
10
- export declare function loadTranslationCache(lang: string): Map<string, string>;
11
- export declare function saveTranslationCache(lang: string, cache: Map<string, string>): void;
12
- export declare function getTextNodes(root: Node): Text[];
13
- export declare function collectNewTextNodes(node: Node, originalTexts: Map<Node, string>): Text[];
14
- export declare function fetchLanguages(apiBase: string): Promise<Language[]>;
15
- export declare function callTranslateApi(apiBase: string, apiKey: string, domain: string, texts: string[], targetLang: string): Promise<string[]>;
package/dist/translate.js DELETED
@@ -1,100 +0,0 @@
1
- const SKIP_TAGS = new Set([
2
- 'SCRIPT', 'STYLE', 'NOSCRIPT', 'IFRAME',
3
- 'CODE', 'PRE', 'SVG', 'MATH', 'INPUT', 'TEXTAREA',
4
- ]);
5
- export function getSavedLang() {
6
- return localStorage.getItem('translify_lang');
7
- }
8
- export function saveLang(lang) {
9
- localStorage.setItem('translify_lang', lang);
10
- }
11
- export function clearSavedLang() {
12
- localStorage.removeItem('translify_lang');
13
- }
14
- export function loadTranslationCache(lang) {
15
- try {
16
- const stored = localStorage.getItem(`translify_cache_${lang}`);
17
- return stored ? new Map(Object.entries(JSON.parse(stored))) : new Map();
18
- }
19
- catch (_a) {
20
- return new Map();
21
- }
22
- }
23
- export function saveTranslationCache(lang, cache) {
24
- try {
25
- const obj = {};
26
- cache.forEach((v, k) => { obj[k] = v; });
27
- localStorage.setItem(`translify_cache_${lang}`, JSON.stringify(obj));
28
- }
29
- catch (_a) { }
30
- }
31
- export function getTextNodes(root) {
32
- const nodes = [];
33
- const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
34
- acceptNode(node) {
35
- var _a, _b, _c, _d, _e, _f;
36
- const text = node;
37
- if (!((_a = text.textContent) === null || _a === void 0 ? void 0 : _a.trim()))
38
- return NodeFilter.FILTER_REJECT;
39
- if (SKIP_TAGS.has(((_c = (_b = text.parentElement) === null || _b === void 0 ? void 0 : _b.tagName) !== null && _c !== void 0 ? _c : '')))
40
- return NodeFilter.FILTER_REJECT;
41
- if (((_e = (_d = text.textContent) === null || _d === void 0 ? void 0 : _d.trim().length) !== null && _e !== void 0 ? _e : 0) > 5000)
42
- return NodeFilter.FILTER_REJECT;
43
- if ((_f = text.parentElement) === null || _f === void 0 ? void 0 : _f.closest('[translate="no"]'))
44
- return NodeFilter.FILTER_REJECT;
45
- return NodeFilter.FILTER_ACCEPT;
46
- },
47
- });
48
- let n;
49
- while ((n = walker.nextNode()))
50
- nodes.push(n);
51
- return nodes;
52
- }
53
- export function collectNewTextNodes(node, originalTexts) {
54
- var _a, _b, _c, _d, _e;
55
- const nodes = [];
56
- if (node.nodeType === Node.TEXT_NODE) {
57
- const t = node;
58
- if (!originalTexts.has(t) && ((_a = t.textContent) === null || _a === void 0 ? void 0 : _a.trim()))
59
- nodes.push(t);
60
- }
61
- else if (node.nodeType === Node.ELEMENT_NODE) {
62
- const walker = document.createTreeWalker(node, NodeFilter.SHOW_TEXT);
63
- let n;
64
- while ((n = walker.nextNode())) {
65
- const t = n;
66
- if (!originalTexts.has(t) &&
67
- ((_b = t.textContent) === null || _b === void 0 ? void 0 : _b.trim()) &&
68
- !SKIP_TAGS.has((_d = (_c = t.parentElement) === null || _c === void 0 ? void 0 : _c.tagName) !== null && _d !== void 0 ? _d : '') &&
69
- !((_e = t.parentElement) === null || _e === void 0 ? void 0 : _e.closest('[translate="no"]'))) {
70
- nodes.push(t);
71
- }
72
- }
73
- }
74
- return nodes;
75
- }
76
- export async function fetchLanguages(apiBase) {
77
- const res = await fetch(`${apiBase}/translate/languages`);
78
- const json = await res.json();
79
- return json.data.languages;
80
- }
81
- export async function callTranslateApi(apiBase, apiKey, domain, texts, targetLang) {
82
- const results = [];
83
- for (let i = 0; i < texts.length; i += 100) {
84
- const chunk = texts.slice(i, i + 100);
85
- const res = await fetch(`${apiBase}/translate`, {
86
- method: 'POST',
87
- headers: {
88
- 'Content-Type': 'application/json',
89
- 'x-api-key': apiKey,
90
- 'x-domain': domain,
91
- },
92
- body: JSON.stringify({ texts: chunk, targetLanguage: targetLang, sourceLanguage: 'auto' }),
93
- });
94
- const json = await res.json();
95
- if (!json.success)
96
- throw new Error(json.message || 'Translation failed');
97
- results.push(...json.data.translations);
98
- }
99
- return results;
100
- }