Skip to content

Commit bc940be

Browse files
feat: allow global functions, directive and component to be renamed
Co-authored-by: Steve Axtmann <steve.axtmann@runway36.de>
1 parent aa62b38 commit bc940be

File tree

3 files changed

+151
-9
lines changed

3 files changed

+151
-9
lines changed

__tests__/vue/globals.spec.ts

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
import { beforeEach, describe, expect, it } from 'vitest'
2+
3+
import { FluentBundle, FluentResource } from '@fluent/bundle'
4+
import ftl from '@fluent/dedent'
5+
6+
import { mountWithFluent } from '../utils'
7+
8+
import { createFluentVue } from '../../src'
9+
10+
describe('globals', () => {
11+
let bundle: FluentBundle
12+
13+
beforeEach(() => {
14+
bundle = new FluentBundle('en-US')
15+
})
16+
17+
it('can rename t directive', () => {
18+
const fluent = createFluentVue({
19+
bundles: [bundle],
20+
globals: {
21+
directive: 'test',
22+
},
23+
})
24+
25+
// Arrange
26+
bundle.addResource(
27+
new FluentResource(ftl`
28+
link = Link text
29+
`),
30+
)
31+
32+
const component = {
33+
template: '<a v-test:link href="/foo">Fallback text</a>',
34+
}
35+
36+
// Act
37+
const mounted = mountWithFluent(fluent, component)
38+
39+
// Assert
40+
expect(mounted.html()).toEqual('<a href="/foo">Link text</a>')
41+
})
42+
43+
it('can rename global $t', () => {
44+
const fluent = createFluentVue({
45+
bundles: [bundle],
46+
globals: {
47+
functions: {
48+
format: '$test',
49+
},
50+
},
51+
})
52+
53+
// Arrange
54+
bundle.addResource(
55+
new FluentResource(ftl`
56+
message = Hello, { $name }!
57+
`),
58+
)
59+
60+
const component = {
61+
data: () => ({
62+
name: 'John',
63+
}),
64+
template: '<div>{{ $test("message", { name }) }}</div>',
65+
}
66+
67+
// Act
68+
const mounted = mountWithFluent(fluent, component)
69+
70+
// Assert
71+
expect(mounted.html()).toEqual('<div>Hello, \u{2068}John\u{2069}!</div>')
72+
})
73+
74+
it('can rename global $ta', () => {
75+
const fluent = createFluentVue({
76+
bundles: [bundle],
77+
globals: {
78+
functions: {
79+
formatAttrs: '$test',
80+
},
81+
},
82+
})
83+
84+
// Arrange
85+
bundle.addResource(
86+
new FluentResource(ftl`
87+
key =
88+
.attr = Attr value
89+
`),
90+
)
91+
92+
const component = {
93+
template: '<div v-bind="$test(\'key\')"></div>',
94+
}
95+
96+
// Act
97+
const mounted = mountWithFluent(fluent, component)
98+
99+
// Assert
100+
expect(mounted.html()).toEqual('<div attr="Attr value"></div>')
101+
})
102+
103+
it('can rename component', () => {
104+
const fluent = createFluentVue({
105+
bundles: [bundle],
106+
globals: {
107+
component: 'test',
108+
},
109+
})
110+
111+
// Arrange
112+
bundle.addResource(
113+
new FluentResource(ftl`
114+
key = Inner data
115+
`),
116+
)
117+
118+
const component = {
119+
template: '<test path="key"></test>',
120+
}
121+
122+
// Act
123+
const mounted = mountWithFluent(fluent, component)
124+
125+
// Assert
126+
expect(mounted.html()).toEqual('<span>Inner data</span>')
127+
})
128+
})

src/index.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,25 +51,30 @@ export function createFluentVue(options: FluentVueOptions): FluentVue {
5151
formatWithAttrs: rootContext.formatWithAttrs.bind(rootContext),
5252

5353
install(vue) {
54+
const globalFormatName = options.globals?.functions?.format || '$t'
55+
const globalFormatAttrsName = options.globals?.functions?.formatAttrs || '$ta'
56+
const directiveName = options.globals?.directive || 't'
57+
const componentName = options.globals?.component || 'i18n'
58+
5459
if (isVue3) {
5560
const vue3 = vue as Vue3
5661

5762
vue3.provide(RootContextSymbol, rootContext)
5863

59-
vue3.config.globalProperties.$t = function (
64+
vue3.config.globalProperties[globalFormatName] = function (
6065
key: string,
6166
value?: Record<string, FluentVariable>,
6267
) {
6368
return getContext(rootContext, this as Vue3Component).format(key, value)
6469
}
65-
vue3.config.globalProperties.$ta = function (
70+
vue3.config.globalProperties[globalFormatAttrsName] = function (
6671
key: string,
6772
value?: Record<string, FluentVariable>,
6873
) {
6974
return getContext(rootContext, this as Vue3Component).formatAttrs(key, value)
7075
}
7176

72-
vue3.directive('t', createVue3Directive(rootContext))
77+
vue3.directive(directiveName, createVue3Directive(rootContext))
7378
}
7479
else {
7580
const vue2 = vue as Vue2
@@ -82,17 +87,17 @@ export function createFluentVue(options: FluentVueOptions): FluentVue {
8287
},
8388
})
8489

85-
vue2.prototype.$t = function (key: string, value?: Record<string, FluentVariable>) {
90+
vue2.prototype[globalFormatName] = function (key: string, value?: Record<string, FluentVariable>) {
8691
return getContext(rootContext, this).format(key, value)
8792
}
88-
vue2.prototype.$ta = function (key: string, value?: Record<string, FluentVariable>) {
93+
vue2.prototype[globalFormatAttrsName] = function (key: string, value?: Record<string, FluentVariable>) {
8994
return getContext(rootContext, this).formatAttrs(key, value)
9095
}
9196

92-
vue2.directive('t', createVue2Directive(rootContext))
97+
vue2.directive(directiveName, createVue2Directive(rootContext))
9398
}
9499

95-
(vue as Vue).component('i18n', component)
100+
(vue as Vue).component(componentName, component)
96101
},
97102
}
98103
}

src/types/index.d.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,17 @@ export interface FluentVueOptions {
1010
warnMissing?: ((key: string) => void) | boolean
1111

1212
/** Custom function for parsing markup */
13-
parseMarkup?: (markup: string) => SimpleNode[]
14-
}
13+
parseMarkup?: (markup: string) => SimpleNode[],
14+
15+
/** Override the names of the global functions and directive to avoid conflicts */
16+
globals?: {
17+
functions?: {
18+
format?: string
19+
formatAttrs?: string
20+
},
21+
component?: string
22+
directive?: string
23+
}}
1524

1625
export interface TranslationContextOptions {
1726
warnMissing: (key: string) => void

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy