@magic-translate/angular 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.2.0](https://github.com/magic-translate/magic-translate/compare/angular-v1.1.0...angular-v1.2.0) (2026-11-06)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **angular:** translate with the secret key on the server ([5f6fae1](https://github.com/magic-translate/magic-translate/commit/5f6fae1fdbaebefe0cb7c62939eb3a03a8419950))
|
|
9
|
+
* id option to edit one use of a text on its own ([9127af3](https://github.com/magic-translate/magic-translate/commit/9127af36de4d63be076e8e192a16584968b4655a))
|
|
10
|
+
|
|
3
11
|
## [1.1.0](https://github.com/magic-translate/magic-translate/compare/angular-v1.0.2...angular-v1.1.0) (2026-11-02)
|
|
4
12
|
|
|
5
13
|
|
package/README.md
CHANGED
|
@@ -160,6 +160,17 @@ formality:
|
|
|
160
160
|
<input [placeholder]="'Your name' | t: { lang: 'fr', formality: 'formal' }" />
|
|
161
161
|
```
|
|
162
162
|
|
|
163
|
+
An `id` lets you edit one use of a text on its own in the webapp, e.g. to
|
|
164
|
+
translate the same "Save" differently on two buttons. Its edited translation
|
|
165
|
+
stays when the text changes. Ids are unique within your account and at most 128
|
|
166
|
+
characters.
|
|
167
|
+
|
|
168
|
+
```html
|
|
169
|
+
<t id="checkout-save">Save</t>
|
|
170
|
+
|
|
171
|
+
<button [title]="'Save' | t: { id: 'checkout-save' }"></button>
|
|
172
|
+
```
|
|
173
|
+
|
|
163
174
|
### Switching languages
|
|
164
175
|
|
|
165
176
|
Inject the `MagicTranslate` service to read or change the current language.
|
|
@@ -217,6 +228,12 @@ original content, and it is translated after hydration. A `<t>` with `[v]`
|
|
|
217
228
|
renders empty on the server, so `$name` never shows, and appears once the app
|
|
218
229
|
runs in the browser.
|
|
219
230
|
|
|
231
|
+
Code that translates on the server, such as a resolver run while prerendering,
|
|
232
|
+
sends your secret key (`p-...`) from the `MAGIC_TRANSLATE_SECRET_KEY`
|
|
233
|
+
environment variable instead of the API key. Create it on your
|
|
234
|
+
[account page](https://magictranslate.io/account) and keep it out of
|
|
235
|
+
`provideMagicTranslate`, which also runs in the browser.
|
|
236
|
+
|
|
220
237
|
## License
|
|
221
238
|
|
|
222
239
|
MIT © [i42 GmbH](https://i42.ch)
|
|
@@ -74,12 +74,13 @@ var MagicTranslate = class MagicTranslate {
|
|
|
74
74
|
sourceLanguage = this.config.sourceLanguage;
|
|
75
75
|
language = computed(() => this.languageOverride() ?? this.config.language, ...ngDevMode ? [{ debugName: "language" }] : /* istanbul ignore next */ []);
|
|
76
76
|
dataLoader = computed(() => {
|
|
77
|
-
const { debug, apiKey, sourceLanguage, _apiUrl, formality } = this.config;
|
|
77
|
+
const { debug, apiKey, secretKey, sourceLanguage, _apiUrl, formality } = this.config;
|
|
78
78
|
const loaderFactory = this.config._loaderFactory ?? defaultLoaderFactory;
|
|
79
79
|
const language = this.language();
|
|
80
80
|
return new DataLoader(loaderFactory({
|
|
81
81
|
debug: !!debug,
|
|
82
82
|
apiKey,
|
|
83
|
+
secretKey,
|
|
83
84
|
lang: language,
|
|
84
85
|
sourceLang: sourceLanguage,
|
|
85
86
|
apiUrl: _apiUrl,
|
|
@@ -168,6 +169,7 @@ function readSource(element) {
|
|
|
168
169
|
var Translate = class Translate {
|
|
169
170
|
lang = input(void 0, ...ngDevMode ? [{ debugName: "lang" }] : /* istanbul ignore next */ []);
|
|
170
171
|
formality = input(void 0, ...ngDevMode ? [{ debugName: "formality" }] : /* istanbul ignore next */ []);
|
|
172
|
+
id = input(void 0, ...ngDevMode ? [{ debugName: "id" }] : /* istanbul ignore next */ []);
|
|
171
173
|
v = input(void 0, ...ngDevMode ? [{ debugName: "v" }] : /* istanbul ignore next */ []);
|
|
172
174
|
magicTranslate = inject(MagicTranslate);
|
|
173
175
|
sanitizer = inject(DomSanitizer);
|
|
@@ -196,6 +198,7 @@ var Translate = class Translate {
|
|
|
196
198
|
const source = this.source();
|
|
197
199
|
const lang = this.lang();
|
|
198
200
|
const formality = this.formality();
|
|
201
|
+
const id = this.id();
|
|
199
202
|
const variables = this.v();
|
|
200
203
|
this.magicTranslate.language();
|
|
201
204
|
if (!source?.html) {
|
|
@@ -215,7 +218,8 @@ var Translate = class Translate {
|
|
|
215
218
|
const requestId = ++this.lastRequestId;
|
|
216
219
|
this.magicTranslate.translate(template, {
|
|
217
220
|
lang,
|
|
218
|
-
formality
|
|
221
|
+
formality,
|
|
222
|
+
id
|
|
219
223
|
}).then((translation) => {
|
|
220
224
|
if (requestId === this.lastRequestId) this.render(source, translation, values);
|
|
221
225
|
});
|
|
@@ -262,6 +266,13 @@ var Translate = class Translate {
|
|
|
262
266
|
isRequired: false,
|
|
263
267
|
transformFunction: null
|
|
264
268
|
},
|
|
269
|
+
id: {
|
|
270
|
+
classPropertyName: "id",
|
|
271
|
+
publicName: "id",
|
|
272
|
+
isSignal: true,
|
|
273
|
+
isRequired: false,
|
|
274
|
+
transformFunction: null
|
|
275
|
+
},
|
|
265
276
|
v: {
|
|
266
277
|
classPropertyName: "v",
|
|
267
278
|
publicName: "v",
|
|
@@ -270,7 +281,10 @@ var Translate = class Translate {
|
|
|
270
281
|
transformFunction: null
|
|
271
282
|
}
|
|
272
283
|
},
|
|
273
|
-
host: {
|
|
284
|
+
host: {
|
|
285
|
+
properties: { "attr.id": "null" },
|
|
286
|
+
styleAttribute: "display: contents"
|
|
287
|
+
},
|
|
274
288
|
viewQueries: [{
|
|
275
289
|
propertyName: "sourceRef",
|
|
276
290
|
first: true,
|
|
@@ -315,7 +329,10 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
315
329
|
#target
|
|
316
330
|
[style.display]="translated() ? 'contents' : 'none'"
|
|
317
331
|
></span>`,
|
|
318
|
-
host: {
|
|
332
|
+
host: {
|
|
333
|
+
style: "display: contents",
|
|
334
|
+
"[attr.id]": "null"
|
|
335
|
+
},
|
|
319
336
|
encapsulation: ViewEncapsulation.None,
|
|
320
337
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
321
338
|
}]
|
|
@@ -338,6 +355,14 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
338
355
|
required: false
|
|
339
356
|
}]
|
|
340
357
|
}],
|
|
358
|
+
id: [{
|
|
359
|
+
type: i0.Input,
|
|
360
|
+
args: [{
|
|
361
|
+
isSignal: true,
|
|
362
|
+
alias: "id",
|
|
363
|
+
required: false
|
|
364
|
+
}]
|
|
365
|
+
}],
|
|
341
366
|
v: [{
|
|
342
367
|
type: i0.Input,
|
|
343
368
|
args: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"magic-translate-angular.mjs","names":[],"sources":["../../src/lib/magic-translate-config.ts","../../src/lib/variables.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 { isDevMode } from '@angular/core';\nimport { libraryName } from '@magic-translate/core';\n\n/**\n * Values that are not translated, referenced as `$name` in the text.\n */\nexport type Variables = Record<string, unknown>;\n\nconst PLACEHOLDER = /\\{(\\d+)\\}/g;\n\nconst escapeRegExp = (text: string) =>\n text.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/**\n * Replaces `$name` with numbered placeholders, `{0}`, `{1}`…, in the order the\n * names first appear, so the API sees the same template as from the React\n * client. Only names that are keys of `variables` are replaced, and the longest\n * key wins, so `$counts` is not read as `$count` followed by \"s\".\n *\n * `replace` can be called for several texts, e.g. every text node of an HTML\n * fragment, and numbers the placeholders across all of them.\n */\nexport function templater(variables: Variables) {\n const names = Object.keys(variables).sort((a, b) => b.length - a.length);\n const pattern =\n names.length > 0\n ? new RegExp(`\\\\$(${names.map(escapeRegExp).join('|')})`, 'g')\n : null;\n const indexes = new Map<string, number>();\n const values: string[] = [];\n\n return {\n values,\n replace(text: string): string {\n if (!pattern) {\n return text;\n }\n return text.replace(pattern, (_, name: string) => {\n let index = indexes.get(name);\n if (index === undefined) {\n index = values.push(String(variables[name] ?? '')) - 1;\n indexes.set(name, index);\n }\n return `{${index}}`;\n });\n },\n unused: () => names.filter((name) => !indexes.has(name)),\n };\n}\n\nexport interface Template {\n template: string;\n values: string[];\n // names that are not in the text, most likely misspelled\n unused: string[];\n}\n\nexport function warnAboutUnused(unused: readonly string[]) {\n if (isDevMode() && unused.length > 0) {\n console.warn(\n `[${libraryName}]: ${unused.map((name) => `$${name}`).join(', ')} not found in the text. Check the spelling, or remove ${unused.length === 1 ? 'it' : 'them'} from the variables.`\n );\n }\n}\n\nexport function toTemplate(text: string, variables: Variables): Template {\n const { replace, values, unused } = templater(variables);\n return { template: replace(text), values, unused: unused() };\n}\n\n/**\n * Puts the values back into a translated text. A placeholder without a value\n * is left as it is.\n */\nexport function fillPlaceholders(text: string, values: readonly string[]) {\n return text.replace(PLACEHOLDER, (placeholder, index: string) =>\n Number(index) < values.length ? values[Number(index)] : placeholder\n );\n}\n\nfunction textNodes(root: Node): Text[] {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);\n const nodes: Text[] = [];\n for (let node = walker.nextNode(); node; node = walker.nextNode()) {\n nodes.push(node as Text);\n }\n return nodes;\n}\n\n/**\n * Like {@link toTemplate}, for HTML. Only text is replaced, never attributes,\n * because only text can be filled in again.\n */\nexport function toHtmlTemplate(html: string, variables: Variables): Template {\n const container = document.createElement('template');\n container.innerHTML = html;\n const { replace, values, unused } = templater(variables);\n textNodes(container.content).forEach((node) => {\n node.data = replace(node.data);\n });\n return { template: container.innerHTML, values, unused: unused() };\n}\n\n/**\n * Fills the placeholders in the text of an element. The values are set as\n * text, so they are never parsed as HTML.\n */\nexport function fillElement(element: Element, values: readonly string[]) {\n textNodes(element).forEach((node) => {\n const filled = fillPlaceholders(node.data, values);\n if (filled !== node.data) {\n node.data = filled;\n }\n });\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';\nimport {\n fillPlaceholders,\n toTemplate,\n Variables,\n warnAboutUnused,\n} from './variables';\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 interface TranslateParams extends Omit<DataLoaderLoadParams, 'text'> {\n /**\n * Values that are not translated, referenced as `$name` in the text. The text\n * is translated once as a template and cached, whatever the values are.\n */\n v?: Variables;\n}\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(\n text: string,\n { v, ...params }: TranslateParams = {}\n ): Promise<string> {\n if (!v) {\n return this.dataLoader().load({ text, ...params });\n }\n const { template, values, unused } = toTemplate(text, v);\n warnAboutUnused(unused);\n return this.dataLoader()\n .load({ text: template, ...params })\n .then((translation) => fillPlaceholders(translation, values));\n }\n\n /** @ignore */\n cacheKey(text: string, params: Omit<TranslateParams, 'v'> = {}): 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 untracked,\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';\nimport {\n fillElement,\n toHtmlTemplate,\n Variables,\n warnAboutUnused,\n} from './variables';\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 // With variables, the source would show `$name`, so it stays hidden and the\n // text is shown with the values filled in until the translation arrives.\n template: `<span\n #source\n [style.display]=\"translated() || v() ? '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 * Values that are not translated, referenced as `$name` in the content. The\n * text is translated once as a template and cached, whatever the values are.\n */\n readonly v = input<Variables | undefined>(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 private lastTemplate?: string;\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 const variables = this.v();\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 const { template, values, unused } = variables\n ? toHtmlTemplate(source.html, variables)\n : { template: source.html, values: [], unused: [] };\n if (template !== this.lastTemplate) {\n this.lastTemplate = template;\n warnAboutUnused(unused);\n }\n if (variables && !untracked(this.translated)) {\n this.render(source, template, values);\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(template, { lang, formality })\n .then((translation) => {\n if (requestId === this.lastRequestId) {\n this.render(source, translation, values);\n }\n });\n });\n }\n\n private render(\n source: Source,\n translation: string,\n values: readonly string[] = []\n ) {\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 (values.length > 0) {\n fillElement(target, values);\n }\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';\nimport { fillPlaceholders, toTemplate, warnAboutUnused } from './variables';\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 * Values that should not be translated go in `v` and are referenced as `$name`:\n * `'Search $count products' | t: { v: { count } }`.\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, { v, ...params }: TranslateParams = {}): string {\n // Only the template is translated, so new values reuse the translation.\n const { template, values, unused } = v\n ? toTemplate(text, v)\n : { template: text, values: [], unused: [] };\n\n if (!text || this.isServer) {\n return fillPlaceholders(template, values);\n }\n\n const key = this.magicTranslate.cacheKey(template, params);\n if (key !== this.key) {\n warnAboutUnused(unused);\n this.key = key;\n this.translation = undefined;\n this.magicTranslate.translate(template, params).then((translation) => {\n if (this.key === key) {\n this.translation = translation;\n this.changeDetectorRef.markForCheck();\n }\n });\n }\n\n return fillPlaceholders(this.translation ?? template, values);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"magic-translate-angular.mjs","names":[],"sources":["../../src/lib/magic-translate-config.ts","../../src/lib/variables.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 { isDevMode } from '@angular/core';\nimport { libraryName } from '@magic-translate/core';\n\n/**\n * Values that are not translated, referenced as `$name` in the text.\n */\nexport type Variables = Record<string, unknown>;\n\nconst PLACEHOLDER = /\\{(\\d+)\\}/g;\n\nconst escapeRegExp = (text: string) =>\n text.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n/**\n * Replaces `$name` with numbered placeholders, `{0}`, `{1}`…, in the order the\n * names first appear, so the API sees the same template as from the React\n * client. Only names that are keys of `variables` are replaced, and the longest\n * key wins, so `$counts` is not read as `$count` followed by \"s\".\n *\n * `replace` can be called for several texts, e.g. every text node of an HTML\n * fragment, and numbers the placeholders across all of them.\n */\nexport function templater(variables: Variables) {\n const names = Object.keys(variables).sort((a, b) => b.length - a.length);\n const pattern =\n names.length > 0\n ? new RegExp(`\\\\$(${names.map(escapeRegExp).join('|')})`, 'g')\n : null;\n const indexes = new Map<string, number>();\n const values: string[] = [];\n\n return {\n values,\n replace(text: string): string {\n if (!pattern) {\n return text;\n }\n return text.replace(pattern, (_, name: string) => {\n let index = indexes.get(name);\n if (index === undefined) {\n index = values.push(String(variables[name] ?? '')) - 1;\n indexes.set(name, index);\n }\n return `{${index}}`;\n });\n },\n unused: () => names.filter((name) => !indexes.has(name)),\n };\n}\n\nexport interface Template {\n template: string;\n values: string[];\n // names that are not in the text, most likely misspelled\n unused: string[];\n}\n\nexport function warnAboutUnused(unused: readonly string[]) {\n if (isDevMode() && unused.length > 0) {\n console.warn(\n `[${libraryName}]: ${unused.map((name) => `$${name}`).join(', ')} not found in the text. Check the spelling, or remove ${unused.length === 1 ? 'it' : 'them'} from the variables.`\n );\n }\n}\n\nexport function toTemplate(text: string, variables: Variables): Template {\n const { replace, values, unused } = templater(variables);\n return { template: replace(text), values, unused: unused() };\n}\n\n/**\n * Puts the values back into a translated text. A placeholder without a value\n * is left as it is.\n */\nexport function fillPlaceholders(text: string, values: readonly string[]) {\n return text.replace(PLACEHOLDER, (placeholder, index: string) =>\n Number(index) < values.length ? values[Number(index)] : placeholder\n );\n}\n\nfunction textNodes(root: Node): Text[] {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);\n const nodes: Text[] = [];\n for (let node = walker.nextNode(); node; node = walker.nextNode()) {\n nodes.push(node as Text);\n }\n return nodes;\n}\n\n/**\n * Like {@link toTemplate}, for HTML. Only text is replaced, never attributes,\n * because only text can be filled in again.\n */\nexport function toHtmlTemplate(html: string, variables: Variables): Template {\n const container = document.createElement('template');\n container.innerHTML = html;\n const { replace, values, unused } = templater(variables);\n textNodes(container.content).forEach((node) => {\n node.data = replace(node.data);\n });\n return { template: container.innerHTML, values, unused: unused() };\n}\n\n/**\n * Fills the placeholders in the text of an element. The values are set as\n * text, so they are never parsed as HTML.\n */\nexport function fillElement(element: Element, values: readonly string[]) {\n textNodes(element).forEach((node) => {\n const filled = fillPlaceholders(node.data, values);\n if (filled !== node.data) {\n node.data = filled;\n }\n });\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';\nimport {\n fillPlaceholders,\n toTemplate,\n Variables,\n warnAboutUnused,\n} from './variables';\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 interface TranslateParams extends Omit<DataLoaderLoadParams, 'text'> {\n /**\n * Values that are not translated, referenced as `$name` in the text. The text\n * is translated once as a template and cached, whatever the values are.\n */\n v?: Variables;\n}\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, secretKey, sourceLanguage, _apiUrl, formality } =\n 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 secretKey,\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(\n text: string,\n { v, ...params }: TranslateParams = {}\n ): Promise<string> {\n if (!v) {\n return this.dataLoader().load({ text, ...params });\n }\n const { template, values, unused } = toTemplate(text, v);\n warnAboutUnused(unused);\n return this.dataLoader()\n .load({ text: template, ...params })\n .then((translation) => fillPlaceholders(translation, values));\n }\n\n /** @ignore */\n cacheKey(text: string, params: Omit<TranslateParams, 'v'> = {}): 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 untracked,\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';\nimport {\n fillElement,\n toHtmlTemplate,\n Variables,\n warnAboutUnused,\n} from './variables';\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 // With variables, the source would show `$name`, so it stays hidden and the\n // text is shown with the values filled in until the translation arrives.\n template: `<span\n #source\n [style.display]=\"translated() || v() ? 'none' : 'contents'\"\n ><ng-content /></span\n ><span\n #target\n [style.display]=\"translated() ? 'contents' : 'none'\"\n ></span>`,\n // `id` is an input, not the element's id, which could clash with the page's.\n host: { style: 'display: contents', '[attr.id]': 'null' },\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 * Lets this use of the text be edited on its own in the webapp. Its edited\n * translation stays when the text changes.\n */\n readonly id = input<string | undefined>(undefined);\n /**\n * Values that are not translated, referenced as `$name` in the content. The\n * text is translated once as a template and cached, whatever the values are.\n */\n readonly v = input<Variables | undefined>(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 private lastTemplate?: string;\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 const id = this.id();\n const variables = this.v();\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 const { template, values, unused } = variables\n ? toHtmlTemplate(source.html, variables)\n : { template: source.html, values: [], unused: [] };\n if (template !== this.lastTemplate) {\n this.lastTemplate = template;\n warnAboutUnused(unused);\n }\n if (variables && !untracked(this.translated)) {\n this.render(source, template, values);\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(template, { lang, formality, id })\n .then((translation) => {\n if (requestId === this.lastRequestId) {\n this.render(source, translation, values);\n }\n });\n });\n }\n\n private render(\n source: Source,\n translation: string,\n values: readonly string[] = []\n ) {\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 (values.length > 0) {\n fillElement(target, values);\n }\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';\nimport { fillPlaceholders, toTemplate, warnAboutUnused } from './variables';\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 * Values that should not be translated go in `v` and are referenced as `$name`:\n * `'Search $count products' | t: { v: { count } }`.\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, { v, ...params }: TranslateParams = {}): string {\n // Only the template is translated, so new values reuse the translation.\n const { template, values, unused } = v\n ? toTemplate(text, v)\n : { template: text, values: [], unused: [] };\n\n if (!text || this.isServer) {\n return fillPlaceholders(template, values);\n }\n\n const key = this.magicTranslate.cacheKey(template, params);\n if (key !== this.key) {\n warnAboutUnused(unused);\n this.key = key;\n this.translation = undefined;\n this.magicTranslate.translate(template, params).then((translation) => {\n if (this.key === key) {\n this.translation = translation;\n this.changeDetectorRef.markForCheck();\n }\n });\n }\n\n return fillPlaceholders(this.translation ?? template, values);\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@magic-translate/angular",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"angular",
|
|
6
6
|
"angular-i18n",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"@angular/platform-browser": ">=20.0.0"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@magic-translate/core": "^1.
|
|
38
|
+
"@magic-translate/core": "^1.6.0",
|
|
39
39
|
"tslib": "^2.8.1"
|
|
40
40
|
},
|
|
41
41
|
"publishConfig": {
|
|
@@ -81,6 +81,11 @@ export declare class MagicTranslate {
|
|
|
81
81
|
export declare class Translate {
|
|
82
82
|
readonly lang: import("@angular/core").InputSignal<"it" | "hr" | "th" | "tr" | "af" | "sq" | "am" | "ar" | "hy" | "az" | "bn" | "bs" | "bg" | "ca" | "zh" | "zh-TW" | "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" | "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" | "uk" | "ur" | "uz" | "vi" | "cy" | undefined>;
|
|
83
83
|
readonly formality: import("@angular/core").InputSignal<"formal" | "informal" | undefined>;
|
|
84
|
+
/**
|
|
85
|
+
* Lets this use of the text be edited on its own in the webapp. Its edited
|
|
86
|
+
* translation stays when the text changes.
|
|
87
|
+
*/
|
|
88
|
+
readonly id: import("@angular/core").InputSignal<string | undefined>;
|
|
84
89
|
/**
|
|
85
90
|
* Values that are not translated, referenced as `$name` in the content. The
|
|
86
91
|
* text is translated once as a template and cached, whatever the values are.
|
|
@@ -108,6 +113,11 @@ export declare class Translate {
|
|
|
108
113
|
"required": false;
|
|
109
114
|
"isSignal": true;
|
|
110
115
|
};
|
|
116
|
+
"id": {
|
|
117
|
+
"alias": "id";
|
|
118
|
+
"required": false;
|
|
119
|
+
"isSignal": true;
|
|
120
|
+
};
|
|
111
121
|
"v": {
|
|
112
122
|
"alias": "v";
|
|
113
123
|
"required": false;
|
|
@@ -1 +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/variables.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;;;;KCLS,YAAY;;;;;;;;;;iBAgBR,UAAU,WAAW;;EAWnB,QAAA;;;UAiBD;EACf;EACA;EAEA;;iBAGc,gBAAgB;iBAQhB,WAAW,cAAc,WAAW,YAAY;;;;;iBAShD,iBAAiB,cAAc;;;;;iBAmB/B,eAAe,cAAc,WAAW,YAAY;;;;;iBAcpD,YAAY,SAAS,SAAS;;;;;YCtFlC,eAAe;iBAEV,wBAAwB,KAAK;;;;;EAK5C,IAAI;;qBAIO;mBACM;mBACA;WAER;WACA;;;;WAKA,kCAAQ;WAIR,oCAAU,OAAA,WAAA;;
|
|
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/variables.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;;;;KCLS,YAAY;;;;;;;;;;iBAgBR,UAAU,WAAW;;EAWnB,QAAA;;;UAiBD;EACf;EACA;EAEA;;iBAGc,gBAAgB;iBAQhB,WAAW,cAAc,WAAW,YAAY;;;;;iBAShD,iBAAiB,cAAc;;;;;iBAmB/B,eAAe,cAAc,WAAW,YAAY;;;;;iBAcpD,YAAY,SAAS,SAAS;;;;;YCtFlC,eAAe;iBAEV,wBAAwB,KAAK;;;;;EAK5C,IAAI;;qBAIO;mBACM;mBACA;WAER;WACA;;;;WAKA,kCAAQ;WAIR,oCAAU,OAAA,WAAA;;EA0BnB,YAAY,UAAU;EAItB,UACE,gBACE,MAAM,WAAU,kBACjB;;EAYH,SAAS,cAAc,SAAQ,KAAK;SA3DzB,MAAA,GAAA,qBAAA;;;qBC8DA;WACF,8BAAI;WACJ,mCAAS;;;;;WAKT,4BAAE;;;;;WAKF,2BAAC,YAAA;mBAEO;mBACA;mBACA;mBAEA;mBAGA;qBACE,oCAAU;UACrB;UACA;;UA0DA;SAlFG,MAAA,GAAA,qBAAA;SAAA,MAAA,GAAA,uBAAA;IAAS;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;IAAA;MAAA;MAAA;MAAA;;;;qBA2GT,UAAC;;;;;;;;;qBCrLD,yBAAyB;mBACnB;mBACA;mBACA;UAET;UACA;EAER,UAAU,gBAAgB,MAAM,WAAU;SAR/B,MAAA,GAAA,qBAAA;SAAA,OAAA,GAAA,kBAAA"}
|