@magic-translate/angular 0.0.0-stage → 0.0.1

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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 - PRESENT i42 GmbH
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/README.md CHANGED
@@ -1,3 +1,171 @@
1
- # Temporary Holding Version
1
+ # @magic-translate/angular
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [![NPM](https://img.shields.io/npm/v/@magic-translate/angular.svg)](https://www.npmjs.com/package/@magic-translate/angular)
4
+ [![npm](https://img.shields.io/npm/dm/@magic-translate/angular.svg)](https://www.npmjs.com/package/@magic-translate/angular)
5
+
6
+ Angular client for [Magic Translate](https://magictranslate.io). Write your
7
+ templates in one language and Magic Translate translates them on the fly.
8
+
9
+ Requires Angular 20 or newer. Works with and without zone.js.
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ npm install --save @magic-translate/angular
15
+ ```
16
+
17
+ Or with yarn:
18
+
19
+ ```bash
20
+ yarn add @magic-translate/angular
21
+ ```
22
+
23
+ ## Setup
24
+
25
+ Add `provideMagicTranslate` to your application config. You can get an API key
26
+ for free at [magictranslate.io](https://magictranslate.io).
27
+
28
+ ```ts
29
+ // app.config.ts
30
+ import { ApplicationConfig } from '@angular/core';
31
+ import { provideMagicTranslate } from '@magic-translate/angular';
32
+
33
+ export const appConfig: ApplicationConfig = {
34
+ providers: [
35
+ provideMagicTranslate({
36
+ apiKey: 'YOUR_API_KEY',
37
+ language: 'de',
38
+ }),
39
+ ],
40
+ };
41
+ ```
42
+
43
+ ## Usage
44
+
45
+ ### `<t>` component
46
+
47
+ Wrap any text, including plain HTML, in `<t>`. The original content is shown
48
+ until its translation has loaded.
49
+
50
+ ```ts
51
+ import { Component, signal } from '@angular/core';
52
+ import { T } from '@magic-translate/angular';
53
+
54
+ @Component({
55
+ selector: 'app-welcome',
56
+ imports: [T],
57
+ template: `
58
+ <h1><t>Welcome to our shop</t></h1>
59
+ <p>
60
+ <t>Click <a href="/sale">here</a> to see <b>today's</b> deals.</t>
61
+ </p>
62
+ <p>
63
+ <t>Hello {{ name() }}</t>
64
+ </p>
65
+ `,
66
+ })
67
+ export class Welcome {
68
+ name = signal('Anna');
69
+ }
70
+ ```
71
+
72
+ The content is re-translated whenever it changes, for example when `name`
73
+ changes in the example above.
74
+
75
+ All translations requested at the same time are sent to the API in a single
76
+ request, and translations are cached, so you can use as many `<t>` components
77
+ as you like.
78
+
79
+ `<mt-translate>` works as an alternative selector, and `Translate` is the same
80
+ component as `T`.
81
+
82
+ Only text and plain HTML elements are allowed inside `<t>`. Other components
83
+ are not, because they cannot survive the translation. The translated markup
84
+ goes through Angular's HTML sanitizer.
85
+
86
+ ### `t` pipe
87
+
88
+ Use the pipe for plain strings, such as attributes, or anywhere a component
89
+ does not fit:
90
+
91
+ ```ts
92
+ import { TranslatePipe } from '@magic-translate/angular';
93
+
94
+ @Component({
95
+ imports: [TranslatePipe],
96
+ template: `<input [placeholder]="'Search products' | t" />`,
97
+ })
98
+ export class Search {}
99
+ ```
100
+
101
+ The pipe returns the original text until the translation has loaded.
102
+
103
+ ### Options per translation
104
+
105
+ Both the component and the pipe can override the target language and the
106
+ formality:
107
+
108
+ ```html
109
+ <t lang="fr" formality="formal">How are you?</t>
110
+
111
+ <input [placeholder]="'Your name' | t: { lang: 'fr', formality: 'formal' }" />
112
+ ```
113
+
114
+ ### Switching languages
115
+
116
+ Inject the `MagicTranslate` service to read or change the current language.
117
+ Every `<t>` component and `t` pipe updates automatically.
118
+
119
+ ```ts
120
+ import { Component, inject } from '@angular/core';
121
+ import { MagicTranslate } from '@magic-translate/angular';
122
+
123
+ @Component({
124
+ selector: 'app-language-switcher',
125
+ template: `
126
+ <select
127
+ [value]="magicTranslate.language()"
128
+ (change)="magicTranslate.setLanguage($any($event.target).value)"
129
+ >
130
+ <option value="en">English</option>
131
+ <option value="de">Deutsch</option>
132
+ <option value="fr">Français</option>
133
+ </select>
134
+ `,
135
+ })
136
+ export class LanguageSwitcher {
137
+ protected readonly magicTranslate = inject(MagicTranslate);
138
+ }
139
+ ```
140
+
141
+ `language` is a signal, so you can also use it in `computed` and `effect`.
142
+
143
+ ### Translating in code
144
+
145
+ To translate a string in TypeScript, call `translate` on the service:
146
+
147
+ ```ts
148
+ const magicTranslate = inject(MagicTranslate);
149
+ const message = await magicTranslate.translate('Your order has been placed');
150
+ ```
151
+
152
+ ## Configuration
153
+
154
+ `provideMagicTranslate` accepts:
155
+
156
+ | Option | Description |
157
+ | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
158
+ | `apiKey` | Required. Your Magic Translate API key. |
159
+ | `language` | Required. The language content is translated to, e.g. `'de'`. |
160
+ | `sourceLanguage` | The language your templates are written in. Detected automatically by default; only set it if automatic detection gives wrong results. |
161
+ | `formality` | `'formal'` or `'informal'`. Not supported for all languages. Can be overridden per translation. |
162
+ | `debug` | Logs requests to the console. |
163
+
164
+ ## Server-side rendering
165
+
166
+ Translations are only loaded in the browser. With SSR the server renders the
167
+ original content, and it is translated after hydration.
168
+
169
+ ## License
170
+
171
+ MIT © [i42 GmbH](https://i42.ch)
@@ -0,0 +1,313 @@
1
+ import { DataLoader, cacheKeyFn, defaultLoaderFactory, libraryName, libraryWebsite } from "@magic-translate/core";
2
+ import * as i0 from "@angular/core";
3
+ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, DestroyRef, Injectable, InjectionToken, PLATFORM_ID, Pipe, SecurityContext, ViewEncapsulation, afterNextRender, computed, effect, inject, input, makeEnvironmentProviders, signal, viewChild } from "@angular/core";
4
+ import { DomSanitizer } from "@angular/platform-browser";
5
+ import { isPlatformServer } from "@angular/common";
6
+ export * from "@magic-translate/core";
7
+ const MAGIC_TRANSLATE_CONFIG = new InjectionToken("MAGIC_TRANSLATE_CONFIG");
8
+ var MagicTranslate = class MagicTranslate {
9
+ config = inject(MAGIC_TRANSLATE_CONFIG);
10
+ languageOverride = signal(null, ...ngDevMode ? [{ debugName: "languageOverride" }] : /* istanbul ignore next */ []);
11
+ apiKey = this.config.apiKey;
12
+ sourceLanguage = this.config.sourceLanguage;
13
+ language = computed(() => this.languageOverride() ?? this.config.language, ...ngDevMode ? [{ debugName: "language" }] : /* istanbul ignore next */ []);
14
+ dataLoader = computed(() => {
15
+ const { debug, apiKey, sourceLanguage, _apiUrl, formality } = this.config;
16
+ const loaderFactory = this.config._loaderFactory ?? defaultLoaderFactory;
17
+ const language = this.language();
18
+ return new DataLoader(loaderFactory({
19
+ debug: !!debug,
20
+ apiKey,
21
+ lang: language,
22
+ sourceLang: sourceLanguage,
23
+ apiUrl: _apiUrl,
24
+ formality
25
+ }), { cacheKeyFn: cacheKeyFn(apiKey, sourceLanguage, language) });
26
+ }, ...ngDevMode ? [{ debugName: "dataLoader" }] : /* istanbul ignore next */ []);
27
+ constructor() {
28
+ if (!this.config.apiKey) throw new Error(`Missing API key. Please get one at ${libraryWebsite}`);
29
+ }
30
+ setLanguage(language) {
31
+ this.languageOverride.set(language);
32
+ }
33
+ translate(text, params = {}) {
34
+ return this.dataLoader().load({
35
+ text,
36
+ ...params
37
+ });
38
+ }
39
+ cacheKey(text, params = {}) {
40
+ return cacheKeyFn(this.apiKey, this.sourceLanguage, this.language())({
41
+ text,
42
+ ...params
43
+ });
44
+ }
45
+ static ɵfac = i0.ɵɵngDeclareFactory({
46
+ minVersion: "12.0.0",
47
+ version: "22.2.3",
48
+ ngImport: i0,
49
+ type: MagicTranslate,
50
+ deps: [],
51
+ target: i0.ɵɵFactoryTarget.Injectable
52
+ });
53
+ static ɵprov = i0.ɵɵngDeclareInjectable({
54
+ minVersion: "12.0.0",
55
+ version: "22.2.3",
56
+ ngImport: i0,
57
+ type: MagicTranslate
58
+ });
59
+ };
60
+ i0.ɵɵngDeclareClassMetadata({
61
+ minVersion: "12.0.0",
62
+ version: "22.2.3",
63
+ ngImport: i0,
64
+ type: MagicTranslate,
65
+ decorators: [{ type: Injectable }],
66
+ ctorParameters: () => []
67
+ });
68
+ function provideMagicTranslate(config) {
69
+ return makeEnvironmentProviders([{
70
+ provide: MAGIC_TRANSLATE_CONFIG,
71
+ useValue: config
72
+ }, MagicTranslate]);
73
+ }
74
+ function readSource(element) {
75
+ const clone = element.cloneNode(true);
76
+ const comments = [];
77
+ let scopeAttribute;
78
+ const walker = document.createTreeWalker(clone, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT);
79
+ for (let node = walker.nextNode(); node; node = walker.nextNode()) {
80
+ if (node.nodeType === Node.COMMENT_NODE) {
81
+ comments.push(node);
82
+ continue;
83
+ }
84
+ const el = node;
85
+ if (el.localName.includes("-")) throw new Error(`Components are not allowed inside \`<t>...</t>\` components. The component found inside the t component is <${el.localName}>.`);
86
+ for (const { name } of Array.from(el.attributes)) {
87
+ if (name.startsWith("_ngcontent-")) scopeAttribute = name;
88
+ if (name.startsWith("_ng") || name.startsWith("ng-reflect-")) el.removeAttribute(name);
89
+ }
90
+ }
91
+ comments.forEach((comment) => comment.parentNode?.removeChild(comment));
92
+ const [, leadingWhitespace, html, trailingWhitespace] = /^(\s*)([\s\S]*?)(\s*)$/.exec(clone.innerHTML);
93
+ return {
94
+ html,
95
+ leadingWhitespace,
96
+ trailingWhitespace,
97
+ scopeAttribute
98
+ };
99
+ }
100
+ var Translate = class Translate {
101
+ lang = input(void 0, ...ngDevMode ? [{ debugName: "lang" }] : /* istanbul ignore next */ []);
102
+ formality = input(void 0, ...ngDevMode ? [{ debugName: "formality" }] : /* istanbul ignore next */ []);
103
+ magicTranslate = inject(MagicTranslate);
104
+ sanitizer = inject(DomSanitizer);
105
+ sourceRef = viewChild.required("source", ...ngDevMode ? [{ debugName: "sourceRef" }] : /* istanbul ignore next */ []);
106
+ targetRef = viewChild.required("target", ...ngDevMode ? [{ debugName: "targetRef" }] : /* istanbul ignore next */ []);
107
+ source = signal(null, ...ngDevMode ? [{ debugName: "source" }] : /* istanbul ignore next */ []);
108
+ translated = signal(false, ...ngDevMode ? [{ debugName: "translated" }] : /* istanbul ignore next */ []);
109
+ lastRequestId = 0;
110
+ constructor() {
111
+ const destroyRef = inject(DestroyRef);
112
+ afterNextRender(() => {
113
+ const element = this.sourceRef().nativeElement;
114
+ const read = () => this.source.set(readSource(element));
115
+ read();
116
+ const observer = new MutationObserver(read);
117
+ observer.observe(element, {
118
+ subtree: true,
119
+ childList: true,
120
+ characterData: true,
121
+ attributes: true
122
+ });
123
+ destroyRef.onDestroy(() => observer.disconnect());
124
+ });
125
+ effect(() => {
126
+ const source = this.source();
127
+ const lang = this.lang();
128
+ const formality = this.formality();
129
+ this.magicTranslate.language();
130
+ if (!source?.html) {
131
+ this.translated.set(false);
132
+ return;
133
+ }
134
+ const requestId = ++this.lastRequestId;
135
+ this.magicTranslate.translate(source.html, {
136
+ lang,
137
+ formality
138
+ }).then((translation) => {
139
+ if (requestId === this.lastRequestId) this.render(source, translation);
140
+ });
141
+ });
142
+ }
143
+ render(source, translation) {
144
+ const target = this.targetRef().nativeElement;
145
+ const html = this.sanitizer.sanitize(SecurityContext.HTML, translation);
146
+ if (html === null) {
147
+ console.warn(`[${libraryName}]: Could not render translation.`);
148
+ return;
149
+ }
150
+ target.innerHTML = `${source.leadingWhitespace}${html}${source.trailingWhitespace}`;
151
+ if (source.scopeAttribute) target.querySelectorAll("*").forEach((el) => el.setAttribute(source.scopeAttribute, ""));
152
+ this.translated.set(true);
153
+ }
154
+ static ɵfac = i0.ɵɵngDeclareFactory({
155
+ minVersion: "12.0.0",
156
+ version: "22.2.3",
157
+ ngImport: i0,
158
+ type: Translate,
159
+ deps: [],
160
+ target: i0.ɵɵFactoryTarget.Component
161
+ });
162
+ static ɵcmp = i0.ɵɵngDeclareComponent({
163
+ minVersion: "17.2.0",
164
+ version: "22.2.3",
165
+ type: Translate,
166
+ isStandalone: true,
167
+ selector: "t, mt-translate",
168
+ inputs: {
169
+ lang: {
170
+ classPropertyName: "lang",
171
+ publicName: "lang",
172
+ isSignal: true,
173
+ isRequired: false,
174
+ transformFunction: null
175
+ },
176
+ formality: {
177
+ classPropertyName: "formality",
178
+ publicName: "formality",
179
+ isSignal: true,
180
+ isRequired: false,
181
+ transformFunction: null
182
+ }
183
+ },
184
+ host: { styleAttribute: "display: contents" },
185
+ viewQueries: [{
186
+ propertyName: "sourceRef",
187
+ first: true,
188
+ predicate: ["source"],
189
+ descendants: true,
190
+ isSignal: true
191
+ }, {
192
+ propertyName: "targetRef",
193
+ first: true,
194
+ predicate: ["target"],
195
+ descendants: true,
196
+ isSignal: true
197
+ }],
198
+ ngImport: i0,
199
+ template: `<span #source [style.display]="translated() ? 'none' : 'contents'"
200
+ ><ng-content /></span
201
+ ><span
202
+ #target
203
+ [style.display]="translated() ? 'contents' : 'none'"
204
+ ></span>`,
205
+ isInline: true,
206
+ changeDetection: i0.ChangeDetectionStrategy.OnPush,
207
+ encapsulation: i0.ViewEncapsulation.None
208
+ });
209
+ };
210
+ i0.ɵɵngDeclareClassMetadata({
211
+ minVersion: "12.0.0",
212
+ version: "22.2.3",
213
+ ngImport: i0,
214
+ type: Translate,
215
+ decorators: [{
216
+ type: Component,
217
+ args: [{
218
+ selector: "t, mt-translate",
219
+ template: `<span #source [style.display]="translated() ? 'none' : 'contents'"
220
+ ><ng-content /></span
221
+ ><span
222
+ #target
223
+ [style.display]="translated() ? 'contents' : 'none'"
224
+ ></span>`,
225
+ host: { style: "display: contents" },
226
+ encapsulation: ViewEncapsulation.None,
227
+ changeDetection: ChangeDetectionStrategy.OnPush
228
+ }]
229
+ }],
230
+ ctorParameters: () => [],
231
+ propDecorators: {
232
+ lang: [{
233
+ type: i0.Input,
234
+ args: [{
235
+ isSignal: true,
236
+ alias: "lang",
237
+ required: false
238
+ }]
239
+ }],
240
+ formality: [{
241
+ type: i0.Input,
242
+ args: [{
243
+ isSignal: true,
244
+ alias: "formality",
245
+ required: false
246
+ }]
247
+ }],
248
+ sourceRef: [{
249
+ type: i0.ViewChild,
250
+ args: ["source", { isSignal: true }]
251
+ }],
252
+ targetRef: [{
253
+ type: i0.ViewChild,
254
+ args: ["target", { isSignal: true }]
255
+ }]
256
+ }
257
+ });
258
+ const T = Translate;
259
+ var TranslatePipe = class TranslatePipe {
260
+ magicTranslate = inject(MagicTranslate);
261
+ changeDetectorRef = inject(ChangeDetectorRef);
262
+ isServer = isPlatformServer(inject(PLATFORM_ID));
263
+ key;
264
+ translation;
265
+ transform(text, params = {}) {
266
+ if (!text || this.isServer) return text;
267
+ const key = this.magicTranslate.cacheKey(text, params);
268
+ if (key !== this.key) {
269
+ this.key = key;
270
+ this.translation = void 0;
271
+ this.magicTranslate.translate(text, params).then((translation) => {
272
+ if (this.key === key) {
273
+ this.translation = translation;
274
+ this.changeDetectorRef.markForCheck();
275
+ }
276
+ });
277
+ }
278
+ return this.translation ?? text;
279
+ }
280
+ static ɵfac = i0.ɵɵngDeclareFactory({
281
+ minVersion: "12.0.0",
282
+ version: "22.2.3",
283
+ ngImport: i0,
284
+ type: TranslatePipe,
285
+ deps: [],
286
+ target: i0.ɵɵFactoryTarget.Pipe
287
+ });
288
+ static ɵpipe = i0.ɵɵngDeclarePipe({
289
+ minVersion: "14.0.0",
290
+ version: "22.2.3",
291
+ ngImport: i0,
292
+ type: TranslatePipe,
293
+ isStandalone: true,
294
+ name: "t",
295
+ pure: false
296
+ });
297
+ };
298
+ i0.ɵɵngDeclareClassMetadata({
299
+ minVersion: "12.0.0",
300
+ version: "22.2.3",
301
+ ngImport: i0,
302
+ type: TranslatePipe,
303
+ decorators: [{
304
+ type: Pipe,
305
+ args: [{
306
+ name: "t",
307
+ pure: false
308
+ }]
309
+ }]
310
+ });
311
+ export { MAGIC_TRANSLATE_CONFIG, MagicTranslate, T, Translate, TranslatePipe, provideMagicTranslate };
312
+
313
+ //# sourceMappingURL=magic-translate-angular.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"magic-translate-angular.mjs","names":[],"sources":["../../src/lib/magic-translate-config.ts","../../src/lib/magic-translate.service.ts","../../src/lib/provide-magic-translate.ts","../../src/lib/translate.component.ts","../../src/lib/translate.pipe.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\nimport { MagicTranslateConfig } from '@magic-translate/core';\n\nexport const MAGIC_TRANSLATE_CONFIG = new InjectionToken<MagicTranslateConfig>(\n 'MAGIC_TRANSLATE_CONFIG'\n);\n","import { computed, inject, Injectable, signal } from '@angular/core';\nimport {\n cacheKeyFn,\n DataLoader,\n DataLoaderLoadParams,\n defaultLoaderFactory,\n Language,\n libraryWebsite,\n} from '@magic-translate/core';\nimport { MAGIC_TRANSLATE_CONFIG } from './magic-translate-config';\n\n/**\n * Type alias to make the language enum more flexible to also allow passing language strings\n * instead of just the enum.\n */\nexport type Languages = `${Language}`;\n\nexport type TranslateParams = Omit<DataLoaderLoadParams, 'text'>;\n\n@Injectable()\nexport class MagicTranslate {\n private readonly config = inject(MAGIC_TRANSLATE_CONFIG);\n private readonly languageOverride = signal<Languages | null>(null);\n\n readonly apiKey = this.config.apiKey;\n readonly sourceLanguage = this.config.sourceLanguage;\n\n /**\n * The language content is currently translated to.\n */\n readonly language = computed(\n () => this.languageOverride() ?? this.config.language\n );\n\n readonly dataLoader = computed(() => {\n const { debug, apiKey, sourceLanguage, _apiUrl, formality } = this.config;\n const loaderFactory = this.config._loaderFactory ?? defaultLoaderFactory;\n const language = this.language();\n\n return new DataLoader<DataLoaderLoadParams, string, string>(\n loaderFactory({\n debug: !!debug,\n apiKey,\n lang: language,\n sourceLang: sourceLanguage,\n apiUrl: _apiUrl,\n formality,\n }),\n { cacheKeyFn: cacheKeyFn(apiKey, sourceLanguage, language) }\n );\n });\n\n constructor() {\n if (!this.config.apiKey) {\n throw new Error(`Missing API key. Please get one at ${libraryWebsite}`);\n }\n }\n\n setLanguage(language: Languages): void {\n this.languageOverride.set(language);\n }\n\n translate(text: string, params: TranslateParams = {}): Promise<string> {\n return this.dataLoader().load({ text, ...params });\n }\n\n /** @ignore */\n cacheKey(text: string, params: TranslateParams = {}): string {\n return cacheKeyFn(\n this.apiKey,\n this.sourceLanguage,\n this.language()\n )({ text, ...params });\n }\n}\n","import { EnvironmentProviders, makeEnvironmentProviders } from '@angular/core';\nimport { MagicTranslateConfig } from '@magic-translate/core';\nimport { MAGIC_TRANSLATE_CONFIG } from './magic-translate-config';\nimport { MagicTranslate } from './magic-translate.service';\n\n/**\n * Sets up Magic Translate for the application. Add it to the `providers` of\n * your application config.\n */\nexport function provideMagicTranslate(\n config: MagicTranslateConfig\n): EnvironmentProviders {\n return makeEnvironmentProviders([\n { provide: MAGIC_TRANSLATE_CONFIG, useValue: config },\n MagicTranslate,\n ]);\n}\n","import {\n afterNextRender,\n ChangeDetectionStrategy,\n Component,\n DestroyRef,\n effect,\n ElementRef,\n inject,\n input,\n SecurityContext,\n signal,\n viewChild,\n ViewEncapsulation,\n} from '@angular/core';\nimport { DomSanitizer } from '@angular/platform-browser';\nimport { libraryName, TranslateOptions } from '@magic-translate/core';\nimport { Languages, MagicTranslate } from './magic-translate.service';\n\ninterface Source {\n html: string;\n leadingWhitespace: string;\n trailingWhitespace: string;\n // The `_ngcontent-*` attribute of the host template, so its component\n // styles still apply to the translated markup.\n scopeAttribute?: string;\n}\n\n/**\n * Turns the projected content into the HTML string that gets translated,\n * without the comments and attributes Angular adds to the DOM.\n */\nfunction readSource(element: HTMLElement): Source {\n const clone = element.cloneNode(true) as HTMLElement;\n const comments: Node[] = [];\n let scopeAttribute: string | undefined;\n\n const walker = document.createTreeWalker(\n clone,\n NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT\n );\n for (let node = walker.nextNode(); node; node = walker.nextNode()) {\n if (node.nodeType === Node.COMMENT_NODE) {\n comments.push(node);\n continue;\n }\n\n const el = node as Element;\n if (el.localName.includes('-')) {\n throw new Error(\n `Components are not allowed inside \\`<t>...</t>\\` components. The component found inside the t component is <${el.localName}>.`\n );\n }\n\n for (const { name } of Array.from(el.attributes)) {\n if (name.startsWith('_ngcontent-')) {\n scopeAttribute = name;\n }\n if (name.startsWith('_ng') || name.startsWith('ng-reflect-')) {\n el.removeAttribute(name);\n }\n }\n }\n comments.forEach((comment) => comment.parentNode?.removeChild(comment));\n\n const [, leadingWhitespace, html, trailingWhitespace] =\n /^(\\s*)([\\s\\S]*?)(\\s*)$/.exec(clone.innerHTML)!;\n\n return { html, leadingWhitespace, trailingWhitespace, scopeAttribute };\n}\n\n@Component({\n selector: 't, mt-translate',\n template: `<span #source [style.display]=\"translated() ? 'none' : 'contents'\"\n ><ng-content /></span\n ><span\n #target\n [style.display]=\"translated() ? 'contents' : 'none'\"\n ></span>`,\n host: { style: 'display: contents' },\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class Translate {\n readonly lang = input<Languages | undefined>(undefined);\n readonly formality = input<TranslateOptions['formality']>(undefined);\n\n private readonly magicTranslate = inject(MagicTranslate);\n private readonly sanitizer = inject(DomSanitizer);\n private readonly sourceRef =\n viewChild.required<ElementRef<HTMLElement>>('source');\n private readonly targetRef =\n viewChild.required<ElementRef<HTMLElement>>('target');\n\n private readonly source = signal<Source | null>(null);\n protected readonly translated = signal(false);\n private lastRequestId = 0;\n\n constructor() {\n const destroyRef = inject(DestroyRef);\n\n afterNextRender(() => {\n const element = this.sourceRef().nativeElement;\n const read = () => this.source.set(readSource(element));\n read();\n\n // Picks up changes to the projected content, such as interpolations.\n const observer = new MutationObserver(read);\n observer.observe(element, {\n subtree: true,\n childList: true,\n characterData: true,\n attributes: true,\n });\n destroyRef.onDestroy(() => observer.disconnect());\n });\n\n effect(() => {\n const source = this.source();\n const lang = this.lang();\n const formality = this.formality();\n // a language switch has to re-translate the content\n this.magicTranslate.language();\n\n if (!source?.html) {\n this.translated.set(false);\n return;\n }\n\n // make sure that we only ever use the response of the most recent request.\n const requestId = ++this.lastRequestId;\n this.magicTranslate\n .translate(source.html, { lang, formality })\n .then((translation) => {\n if (requestId === this.lastRequestId) {\n this.render(source, translation);\n }\n });\n });\n }\n\n private render(source: Source, translation: string) {\n const target = this.targetRef().nativeElement;\n const html = this.sanitizer.sanitize(SecurityContext.HTML, translation);\n if (html === null) {\n console.warn(`[${libraryName}]: Could not render translation.`);\n return;\n }\n\n target.innerHTML = `${source.leadingWhitespace}${html}${source.trailingWhitespace}`;\n if (source.scopeAttribute) {\n target\n .querySelectorAll('*')\n .forEach((el) => el.setAttribute(source.scopeAttribute!, ''));\n }\n this.translated.set(true);\n }\n}\n\nexport const T = Translate;\n","import { isPlatformServer } from '@angular/common';\nimport {\n ChangeDetectorRef,\n inject,\n Pipe,\n PipeTransform,\n PLATFORM_ID,\n} from '@angular/core';\nimport { MagicTranslate, TranslateParams } from './magic-translate.service';\n\n/**\n * Translates a plain string, e.g. for attributes:\n * `<input [placeholder]=\"'Search' | t\" />`. Returns the original text until\n * the translation has loaded.\n */\n@Pipe({ name: 't', pure: false })\nexport class TranslatePipe implements PipeTransform {\n private readonly magicTranslate = inject(MagicTranslate);\n private readonly changeDetectorRef = inject(ChangeDetectorRef);\n private readonly isServer = isPlatformServer(inject(PLATFORM_ID));\n\n private key?: string;\n private translation?: string;\n\n transform(text: string, params: TranslateParams = {}): string {\n if (!text || this.isServer) {\n return text;\n }\n\n const key = this.magicTranslate.cacheKey(text, params);\n if (key !== this.key) {\n this.key = key;\n this.translation = undefined;\n this.magicTranslate.translate(text, params).then((translation) => {\n if (this.key === key) {\n this.translation = translation;\n this.changeDetectorRef.markForCheck();\n }\n });\n }\n\n return this.translation ?? text;\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,44 @@
1
1
  {
2
2
  "name": "@magic-translate/angular",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.0.1",
4
+ "keywords": [
5
+ "angular",
6
+ "magic-translate",
7
+ "i18n",
8
+ "translations",
9
+ "multilanguage"
10
+ ],
11
+ "description": "Angular client for Magic Translate (https://magictranslate.io)",
12
+ "author": "i42 GmbH <info@i42.ch>",
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/magic-translate/magic-translate-angular.git"
16
+ },
17
+ "homepage": "https://magictranslate.io",
18
+ "license": "MIT",
19
+ "engines": {
20
+ "node": ">=22.22.1"
21
+ },
22
+ "peerDependencies": {
23
+ "@angular/common": ">=20.0.0",
24
+ "@angular/core": ">=20.0.0",
25
+ "@angular/platform-browser": ">=20.0.0"
26
+ },
27
+ "dependencies": {
28
+ "@magic-translate/core": "^1.4.0",
29
+ "tslib": "^2.8.1"
30
+ },
31
+ "module": "fesm2022/magic-translate-angular.mjs",
32
+ "typings": "types/magic-translate-angular.d.ts",
33
+ "exports": {
34
+ "./package.json": {
35
+ "default": "./package.json"
36
+ },
37
+ ".": {
38
+ "types": "./types/magic-translate-angular.d.ts",
39
+ "default": "./fesm2022/magic-translate-angular.mjs"
40
+ }
41
+ },
42
+ "sideEffects": false,
43
+ "type": "module"
6
44
  }
@@ -0,0 +1,77 @@
1
+ import { DataLoader, DataLoaderLoadParams, Language, MagicTranslateConfig } from "@magic-translate/core";
2
+ import * as i0 from "@angular/core";
3
+ import { EnvironmentProviders, InjectionToken, PipeTransform } from "@angular/core";
4
+ export * from "@magic-translate/core";
5
+ export declare const MAGIC_TRANSLATE_CONFIG: InjectionToken<MagicTranslateConfig>;
6
+ /**
7
+ * Sets up Magic Translate for the application. Add it to the `providers` of
8
+ * your application config.
9
+ */
10
+ export declare function provideMagicTranslate(config: MagicTranslateConfig): EnvironmentProviders;
11
+ /**
12
+ * Type alias to make the language enum more flexible to also allow passing language strings
13
+ * instead of just the enum.
14
+ */
15
+ export type Languages = `${Language}`;
16
+ export type TranslateParams = Omit<DataLoaderLoadParams, 'text'>;
17
+ export declare class MagicTranslate {
18
+ private readonly config;
19
+ private readonly languageOverride;
20
+ readonly apiKey: string;
21
+ readonly sourceLanguage: "af" | "sq" | "am" | "ar" | "hy" | "az" | "bn" | "bs" | "bg" | "ca" | "zh" | "zh-TW" | "hr" | "cs" | "da" | "fa-AF" | "nl" | "en" | "et" | "fa" | "tl" | "fi" | "fr" | "fr-CA" | "ka" | "de" | "el" | "gu" | "ht" | "ha" | "he" | "hi" | "hu" | "is" | "id" | "ga" | "it" | "ja" | "kn" | "kk" | "ko" | "lv" | "lt" | "mk" | "ms" | "ml" | "mt" | "mr" | "mn" | "no" | "ps" | "pl" | "pt" | "pt-PT" | "pa" | "ro" | "ru" | "sr" | "si" | "sk" | "sl" | "so" | "es" | "es-MX" | "sw" | "sv" | "ta" | "te" | "th" | "tr" | "uk" | "ur" | "uz" | "vi" | "cy" | undefined;
22
+ /**
23
+ * The language content is currently translated to.
24
+ */
25
+ readonly language: import("@angular/core").Signal<"af" | "sq" | "am" | "ar" | "hy" | "az" | "bn" | "bs" | "bg" | "ca" | "zh" | "zh-TW" | "hr" | "cs" | "da" | "fa-AF" | "nl" | "en" | "et" | "fa" | "tl" | "fi" | "fr" | "fr-CA" | "ka" | "de" | "el" | "gu" | "ht" | "ha" | "he" | "hi" | "hu" | "is" | "id" | "ga" | "it" | "ja" | "kn" | "kk" | "ko" | "lv" | "lt" | "mk" | "ms" | "ml" | "mt" | "mr" | "mn" | "no" | "ps" | "pl" | "pt" | "pt-PT" | "pa" | "ro" | "ru" | "sr" | "si" | "sk" | "sl" | "so" | "es" | "es-MX" | "sw" | "sv" | "ta" | "te" | "th" | "tr" | "uk" | "ur" | "uz" | "vi" | "cy">;
26
+ readonly dataLoader: import("@angular/core").Signal<DataLoader<DataLoaderLoadParams, string, string>>;
27
+ constructor();
28
+ setLanguage(language: Languages): void;
29
+ translate(text: string, params?: TranslateParams): Promise<string>;
30
+ /** @ignore */
31
+ cacheKey(text: string, params?: TranslateParams): string;
32
+ static ɵfac: i0.ɵɵFactoryDeclaration<MagicTranslate, never>;
33
+ static ɵprov: i0.ɵɵInjectableDeclaration<any>;
34
+ }
35
+ export declare class Translate {
36
+ readonly lang: import("@angular/core").InputSignal<"af" | "sq" | "am" | "ar" | "hy" | "az" | "bn" | "bs" | "bg" | "ca" | "zh" | "zh-TW" | "hr" | "cs" | "da" | "fa-AF" | "nl" | "en" | "et" | "fa" | "tl" | "fi" | "fr" | "fr-CA" | "ka" | "de" | "el" | "gu" | "ht" | "ha" | "he" | "hi" | "hu" | "is" | "id" | "ga" | "it" | "ja" | "kn" | "kk" | "ko" | "lv" | "lt" | "mk" | "ms" | "ml" | "mt" | "mr" | "mn" | "no" | "ps" | "pl" | "pt" | "pt-PT" | "pa" | "ro" | "ru" | "sr" | "si" | "sk" | "sl" | "so" | "es" | "es-MX" | "sw" | "sv" | "ta" | "te" | "th" | "tr" | "uk" | "ur" | "uz" | "vi" | "cy" | undefined>;
37
+ readonly formality: import("@angular/core").InputSignal<"formal" | "informal" | undefined>;
38
+ private readonly magicTranslate;
39
+ private readonly sanitizer;
40
+ private readonly sourceRef;
41
+ private readonly targetRef;
42
+ private readonly source;
43
+ protected readonly translated: import("@angular/core").WritableSignal<boolean>;
44
+ private lastRequestId;
45
+ constructor();
46
+ private render;
47
+ static ɵfac: i0.ɵɵFactoryDeclaration<Translate, never>;
48
+ static ɵcmp: i0.ɵɵComponentDeclaration<Translate, "t, mt-translate", never, {
49
+ "lang": {
50
+ "alias": "lang";
51
+ "required": false;
52
+ "isSignal": true;
53
+ };
54
+ "formality": {
55
+ "alias": "formality";
56
+ "required": false;
57
+ "isSignal": true;
58
+ };
59
+ }, {}, never, ["*"], true, never>;
60
+ }
61
+ export declare const T: typeof Translate;
62
+ /**
63
+ * Translates a plain string, e.g. for attributes:
64
+ * `<input [placeholder]="'Search' | t" />`. Returns the original text until
65
+ * the translation has loaded.
66
+ */
67
+ export declare class TranslatePipe implements PipeTransform {
68
+ private readonly magicTranslate;
69
+ private readonly changeDetectorRef;
70
+ private readonly isServer;
71
+ private key?;
72
+ private translation?;
73
+ transform(text: string, params?: TranslateParams): string;
74
+ static ɵfac: i0.ɵɵFactoryDeclaration<TranslatePipe, never>;
75
+ static ɵpipe: i0.ɵɵPipeDeclaration<TranslatePipe, "t", true>;
76
+ }
77
+ //# sourceMappingURL=magic-translate-angular.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"magic-translate-angular.d.ts","names":[],"sources":["../../src/lib/magic-translate-config.ts","../../src/lib/provide-magic-translate.ts","../../src/lib/magic-translate.service.ts","../../src/lib/translate.component.ts","../../src/lib/translate.pipe.ts"],"mappings":";;;;qBAGa,wBAAsB,eAAA;;;;;wBCMnB,sBACd,QAAQ,uBACP;;;;;YCIS,eAAe;YAEf,kBAAkB,KAAK;qBAGtB;mBACM;mBACA;WAER;WACA;;;;WAKA,kCAAQ;WAIR,oCAAU,OAAA,WAAA;;EAwBnB,YAAY,UAAU;EAItB,UAAU,cAAc,SAAQ,kBAAuB;;EAKvD,SAAS,cAAc,SAAQ;SA/CpB,MAAA,GAAA,qBAAA;;;qBC8DA;WACF,8BAAI;WACJ,mCAAS;mBAED;mBACA;mBACA;mBAEA;mBAGA;qBACE,oCAAU;UACrB;;UA6CA;SA1DG,MAAA,GAAA,qBAAA;SAAA,MAAA,GAAA,uBAAA;IAAS;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;;;qBA4ET,UAAC;;;;;;qBC9ID,yBAAyB;mBACnB;mBACA;mBACA;UAET;UACA;EAER,UAAU,cAAc,SAAQ;SARrB,MAAA,GAAA,qBAAA;SAAA,OAAA,GAAA,kBAAA"}