@i18n-micro/core 1.1.0 → 1.1.2
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/dist/base.d.ts +2 -2
- package/dist/helpers.d.ts +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +4 -5
- package/dist/index.mjs +137 -329
- package/package.json +2 -2
- package/src/base.ts +15 -48
- package/src/format-service.ts +1 -1
- package/src/helpers.ts +1 -1
- package/src/index.ts +11 -5
- package/src/translation.ts +2 -4
- package/tests/base.test.ts +6 -11
- package/tests/core.test.ts +1 -1
- package/tests/helpers.test.ts +3 -3
- package/vite.config.mts +2 -5
- package/dist/route-service.d.ts +0 -41
- package/src/route-service.ts +0 -469
- package/tests/route-service.test.ts +0 -347
|
@@ -1,347 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
RouteLocationAsPathGeneric,
|
|
3
|
-
RouteLocationNamedRaw,
|
|
4
|
-
RouteLocationNormalizedLoaded,
|
|
5
|
-
RouteLocationRaw,
|
|
6
|
-
RouteLocationResolvedGeneric,
|
|
7
|
-
Router,
|
|
8
|
-
} from 'vue-router'
|
|
9
|
-
import type { ModuleOptionsExtend } from '@i18n-micro/types'
|
|
10
|
-
import { RouteService } from '../src'
|
|
11
|
-
|
|
12
|
-
describe('RouteService', () => {
|
|
13
|
-
let routeService: RouteService
|
|
14
|
-
let mockRouter: jest.Mocked<Router>
|
|
15
|
-
let mockI18nConfig: ModuleOptionsExtend
|
|
16
|
-
let navigateToMock: jest.Mock
|
|
17
|
-
|
|
18
|
-
beforeEach(() => {
|
|
19
|
-
// Mock Router
|
|
20
|
-
mockRouter = {
|
|
21
|
-
currentRoute: { value: { params: { locale: 'en' } } },
|
|
22
|
-
resolve: jest.fn((to: RouteLocationRaw | string) => ({
|
|
23
|
-
fullPath: typeof to === 'string' ? to : to.path || '',
|
|
24
|
-
path: typeof to === 'string' ? to : to.path || '',
|
|
25
|
-
query: {},
|
|
26
|
-
hash: '',
|
|
27
|
-
params: {},
|
|
28
|
-
})) as unknown as jest.MockedFunction<Router['resolve']>,
|
|
29
|
-
hasRoute: jest.fn((_name: string) => false) as jest.MockedFunction<Router['hasRoute']>,
|
|
30
|
-
push: jest.fn(() => Promise.resolve()) as unknown as jest.MockedFunction<Router['push']>,
|
|
31
|
-
} as unknown as jest.Mocked<Router>
|
|
32
|
-
|
|
33
|
-
// Mock ModuleOptionsExtend
|
|
34
|
-
mockI18nConfig = {
|
|
35
|
-
apiBaseUrl: '',
|
|
36
|
-
dateBuild: 0,
|
|
37
|
-
disablePageLocales: false,
|
|
38
|
-
isSSG: false,
|
|
39
|
-
defaultLocale: 'en',
|
|
40
|
-
strategy: 'prefix_except_default',
|
|
41
|
-
locales: [
|
|
42
|
-
{ code: 'en', iso: 'en-US' },
|
|
43
|
-
{ code: 'de', iso: 'de-DE' },
|
|
44
|
-
{ code: 'ru', iso: 'ru-RU' },
|
|
45
|
-
],
|
|
46
|
-
hashMode: false,
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
navigateToMock = jest.fn()
|
|
50
|
-
|
|
51
|
-
// Initialize RouteService (no setCookie - plugin handles cookies)
|
|
52
|
-
routeService = new RouteService(
|
|
53
|
-
mockI18nConfig,
|
|
54
|
-
mockRouter,
|
|
55
|
-
null,
|
|
56
|
-
null,
|
|
57
|
-
navigateToMock,
|
|
58
|
-
)
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
test('getCurrentLocale should return the correct locale', () => {
|
|
62
|
-
const locale = routeService.getCurrentLocale()
|
|
63
|
-
expect(locale).toBe('en')
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
test('getCurrentLocale should return the hash locale if hashMode is enabled', () => {
|
|
67
|
-
const mockI18nConfigWithHashMode = { ...mockI18nConfig, hashMode: true }
|
|
68
|
-
routeService = new RouteService(mockI18nConfigWithHashMode, mockRouter, 'de', null, navigateToMock)
|
|
69
|
-
const locale = routeService.getCurrentLocale()
|
|
70
|
-
expect(locale).toBe('de')
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
test('getCurrentLocale should return the noPrefix locale if noPrefix strategy is enabled', () => {
|
|
74
|
-
const mockI18nConfigWithNoPrefix: ModuleOptionsExtend = { ...mockI18nConfig, strategy: 'no_prefix' }
|
|
75
|
-
routeService = new RouteService(mockI18nConfigWithNoPrefix, mockRouter, null, 'ru', navigateToMock)
|
|
76
|
-
const locale = routeService.getCurrentLocale()
|
|
77
|
-
expect(locale).toBe('ru')
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
test('getCurrentName should return the display name of the current locale', () => {
|
|
81
|
-
const mockI18nConfigWithDisplayName = {
|
|
82
|
-
...mockI18nConfig,
|
|
83
|
-
locales: [
|
|
84
|
-
{ code: 'en', iso: 'en-US', displayName: 'English' },
|
|
85
|
-
{ code: 'de', iso: 'de-DE', displayName: 'German' },
|
|
86
|
-
{ code: 'ru', iso: 'ru-RU', displayName: 'Russian' },
|
|
87
|
-
],
|
|
88
|
-
}
|
|
89
|
-
routeService = new RouteService(mockI18nConfigWithDisplayName, mockRouter, null, null, navigateToMock)
|
|
90
|
-
const route = { name: 'localized-about-en' } as RouteLocationNormalizedLoaded
|
|
91
|
-
const displayName = routeService.getCurrentName(route)
|
|
92
|
-
expect(displayName).toBe('English')
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
test('getRouteName should return the correct route name without locale suffix', () => {
|
|
96
|
-
const route = { name: 'localized-about-en' } as RouteLocationNamedRaw
|
|
97
|
-
const routeName = routeService.getRouteName(route, 'en')
|
|
98
|
-
expect(routeName).toBe('about')
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
test('switchLocaleRoute should return the correct route for the new locale', () => {
|
|
102
|
-
const route = { name: 'localized-about-en', params: {} } as RouteLocationNamedRaw
|
|
103
|
-
const i18nRouteParams = { de: { param1: 'value1' } }
|
|
104
|
-
const newRoute = routeService.switchLocaleRoute('en', 'de', route, i18nRouteParams)
|
|
105
|
-
expect(newRoute).toEqual({
|
|
106
|
-
name: 'localized-about',
|
|
107
|
-
hash: undefined,
|
|
108
|
-
query: undefined,
|
|
109
|
-
params: { param1: 'value1', locale: 'de' },
|
|
110
|
-
})
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
test('getLocalizedRoute should return the correct localized route', () => {
|
|
114
|
-
const route = { name: 'about', params: {} } as RouteLocationNormalizedLoaded
|
|
115
|
-
const to = { path: '/about' } as RouteLocationResolvedGeneric
|
|
116
|
-
mockRouter.resolve.mockReturnValueOnce({
|
|
117
|
-
fullPath: '/en/about',
|
|
118
|
-
path: '/about',
|
|
119
|
-
query: {},
|
|
120
|
-
hash: '',
|
|
121
|
-
params: {},
|
|
122
|
-
} as RouteLocationResolvedGeneric)
|
|
123
|
-
const localizedRoute = routeService.getLocalizedRoute(to, route, 'en')
|
|
124
|
-
expect(localizedRoute).toEqual({
|
|
125
|
-
path: '/about',
|
|
126
|
-
fullPath: '/about',
|
|
127
|
-
query: {},
|
|
128
|
-
params: {},
|
|
129
|
-
hash: '',
|
|
130
|
-
})
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
test('switchLocaleLogic should switch the locale and navigate to the new route', async () => {
|
|
134
|
-
const route = { name: 'about-en', params: {} } as RouteLocationResolvedGeneric
|
|
135
|
-
const i18nRouteParams = { de: { param1: 'value1' } }
|
|
136
|
-
await routeService.switchLocaleLogic('de', i18nRouteParams, route)
|
|
137
|
-
|
|
138
|
-
// Check that push was called with correct arguments
|
|
139
|
-
expect(mockRouter.push).toHaveBeenCalledWith({
|
|
140
|
-
name: 'localized-about',
|
|
141
|
-
params: { param1: 'value1', locale: 'de' },
|
|
142
|
-
hash: undefined,
|
|
143
|
-
query: undefined,
|
|
144
|
-
})
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
test('getFullPathWithBaseUrl should return the correct full path with base URL', () => {
|
|
148
|
-
const currentLocale = { code: 'de', iso: 'de-DE', baseUrl: 'https://example.com/de' }
|
|
149
|
-
const route = { path: '/about' } as RouteLocationRaw
|
|
150
|
-
const fullPath = routeService.getFullPathWithBaseUrl(currentLocale, route)
|
|
151
|
-
expect(fullPath).toBe('https://example.com/de/about')
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
test('resolveLocalizedRoute should return the correct localized route', () => {
|
|
155
|
-
const to = { path: '/about' } as RouteLocationAsPathGeneric
|
|
156
|
-
mockRouter.resolve.mockReturnValueOnce({
|
|
157
|
-
fullPath: '/en/about',
|
|
158
|
-
path: '/about',
|
|
159
|
-
query: {},
|
|
160
|
-
hash: '',
|
|
161
|
-
params: {},
|
|
162
|
-
} as RouteLocationResolvedGeneric)
|
|
163
|
-
const localizedRoute = routeService.resolveLocalizedRoute(to, 'en')
|
|
164
|
-
expect(localizedRoute).toEqual({
|
|
165
|
-
path: '/about',
|
|
166
|
-
fullPath: '/about',
|
|
167
|
-
query: {},
|
|
168
|
-
params: {},
|
|
169
|
-
hash: '',
|
|
170
|
-
})
|
|
171
|
-
})
|
|
172
|
-
|
|
173
|
-
test('getCurrentLocale should return defaultLocale if locale is missing in route params', () => {
|
|
174
|
-
mockRouter.currentRoute.value.params = {} // Remove locale from params
|
|
175
|
-
mockRouter.currentRoute.value.path = '/' // No locale in path
|
|
176
|
-
const locale = routeService.getCurrentLocale()
|
|
177
|
-
expect(locale).toBe('en') // defaultLocale
|
|
178
|
-
})
|
|
179
|
-
|
|
180
|
-
test('getCurrentLocale should extract locale from URL path when route params are missing', () => {
|
|
181
|
-
mockRouter.currentRoute.value.params = {} // Remove locale from params
|
|
182
|
-
mockRouter.currentRoute.value.path = '/ru/sdfsdf' // URL with locale prefix
|
|
183
|
-
const locale = routeService.getCurrentLocale()
|
|
184
|
-
expect(locale).toBe('ru') // Should extract from URL
|
|
185
|
-
})
|
|
186
|
-
|
|
187
|
-
test('getCurrentLocale should return defaultLocale for prefix_except_default when URL has no locale prefix', () => {
|
|
188
|
-
routeService = new RouteService(
|
|
189
|
-
mockI18nConfig, // strategy: prefix_except_default
|
|
190
|
-
mockRouter,
|
|
191
|
-
null,
|
|
192
|
-
null,
|
|
193
|
-
navigateToMock,
|
|
194
|
-
() => 'de', // getter from plugin (cookie/state)
|
|
195
|
-
)
|
|
196
|
-
mockRouter.currentRoute.value.params = {} // Remove locale from params
|
|
197
|
-
mockRouter.currentRoute.value.path = '/' // No locale in path
|
|
198
|
-
const locale = routeService.getCurrentLocale()
|
|
199
|
-
// For prefix_except_default: URL without locale = defaultLocale (SEO requirement)
|
|
200
|
-
// Getter is NOT used because URL explicitly indicates defaultLocale
|
|
201
|
-
expect(locale).toBe('en')
|
|
202
|
-
})
|
|
203
|
-
|
|
204
|
-
test('getCurrentLocale should use getDefaultLocale for no_prefix strategy', () => {
|
|
205
|
-
const noPrefixConfig = { ...mockI18nConfig, strategy: 'no_prefix' as const }
|
|
206
|
-
routeService = new RouteService(
|
|
207
|
-
noPrefixConfig,
|
|
208
|
-
mockRouter,
|
|
209
|
-
null,
|
|
210
|
-
'de', // noPrefixDefault
|
|
211
|
-
navigateToMock,
|
|
212
|
-
() => 'de', // getter from plugin (cookie/state)
|
|
213
|
-
)
|
|
214
|
-
mockRouter.currentRoute.value.params = {} // Remove locale from params
|
|
215
|
-
mockRouter.currentRoute.value.path = '/' // No locale in path
|
|
216
|
-
const locale = routeService.getCurrentLocale()
|
|
217
|
-
// For no_prefix: getter/noPrefixDefault determines locale
|
|
218
|
-
expect(locale).toBe('de')
|
|
219
|
-
})
|
|
220
|
-
|
|
221
|
-
test('getCurrentLocale should prioritize route params over URL path', () => {
|
|
222
|
-
mockRouter.currentRoute.value.params = { locale: 'de' } // Route params have locale
|
|
223
|
-
mockRouter.currentRoute.value.path = '/ru/sdfsdf' // URL has different locale
|
|
224
|
-
const locale = routeService.getCurrentLocale()
|
|
225
|
-
expect(locale).toBe('de') // Should use route params
|
|
226
|
-
})
|
|
227
|
-
|
|
228
|
-
test('getCurrentLocale should prioritize URL path over getDefaultLocale', () => {
|
|
229
|
-
routeService = new RouteService(
|
|
230
|
-
mockI18nConfig,
|
|
231
|
-
mockRouter,
|
|
232
|
-
null,
|
|
233
|
-
null,
|
|
234
|
-
navigateToMock,
|
|
235
|
-
() => 'de', // getter
|
|
236
|
-
)
|
|
237
|
-
mockRouter.currentRoute.value.params = {} // No locale in params
|
|
238
|
-
mockRouter.currentRoute.value.path = '/ru/sdfsdf' // URL has locale
|
|
239
|
-
const locale = routeService.getCurrentLocale()
|
|
240
|
-
expect(locale).toBe('ru') // Should use URL path, not getter
|
|
241
|
-
})
|
|
242
|
-
|
|
243
|
-
test('getCurrentName should return null if displayName is missing', () => {
|
|
244
|
-
const mockI18nConfigWithoutDisplayName = {
|
|
245
|
-
...mockI18nConfig,
|
|
246
|
-
locales: [
|
|
247
|
-
{ code: 'en', iso: 'en-US' }, // displayName is missing
|
|
248
|
-
{ code: 'de', iso: 'de-DE' },
|
|
249
|
-
{ code: 'ru', iso: 'ru-RU' },
|
|
250
|
-
],
|
|
251
|
-
}
|
|
252
|
-
routeService = new RouteService(mockI18nConfigWithoutDisplayName, mockRouter, null, null, navigateToMock)
|
|
253
|
-
const route = { name: 'localized-about-en' } as RouteLocationNormalizedLoaded
|
|
254
|
-
const displayName = routeService.getCurrentName(route)
|
|
255
|
-
expect(displayName).toBeNull()
|
|
256
|
-
})
|
|
257
|
-
|
|
258
|
-
test('switchLocaleRoute should handle missing i18nRouteParams', () => {
|
|
259
|
-
const route = { name: 'localized-about-en', params: {} } as RouteLocationResolvedGeneric
|
|
260
|
-
const newRoute = routeService.switchLocaleRoute('en', 'de', route, {})
|
|
261
|
-
expect(newRoute).toEqual({
|
|
262
|
-
name: 'localized-about',
|
|
263
|
-
hash: undefined,
|
|
264
|
-
query: undefined,
|
|
265
|
-
params: { locale: 'de' },
|
|
266
|
-
})
|
|
267
|
-
})
|
|
268
|
-
|
|
269
|
-
test('getFullPathWithBaseUrl should handle missing baseUrl', () => {
|
|
270
|
-
const currentLocale = { code: 'de', iso: 'de-DE' } // baseUrl is missing
|
|
271
|
-
const route = { path: '/about' } as RouteLocationRaw
|
|
272
|
-
const fullPath = routeService.getFullPathWithBaseUrl(currentLocale, route)
|
|
273
|
-
expect(fullPath).toBe('/about')
|
|
274
|
-
})
|
|
275
|
-
|
|
276
|
-
test('handlePrefixStrategy should handle invalid route', () => {
|
|
277
|
-
const to = '/invalid-route'
|
|
278
|
-
mockRouter.resolve.mockReturnValueOnce({
|
|
279
|
-
fullPath: '/invalid-route',
|
|
280
|
-
path: '/invalid-route',
|
|
281
|
-
query: {},
|
|
282
|
-
hash: '',
|
|
283
|
-
params: {},
|
|
284
|
-
} as RouteLocationResolvedGeneric)
|
|
285
|
-
const processedTo = routeService['handlePrefixStrategy'](to)
|
|
286
|
-
expect(processedTo).toEqual(to)
|
|
287
|
-
})
|
|
288
|
-
|
|
289
|
-
test('createLocalizedRoute should handle invalid route', () => {
|
|
290
|
-
const to = '/invalid-route'
|
|
291
|
-
const route = { name: 'about', params: {} } as RouteLocationNormalizedLoaded
|
|
292
|
-
mockRouter.resolve.mockReturnValueOnce({
|
|
293
|
-
fullPath: '/invalid-route',
|
|
294
|
-
path: '/invalid-route',
|
|
295
|
-
query: {},
|
|
296
|
-
hash: '',
|
|
297
|
-
params: {},
|
|
298
|
-
} as RouteLocationResolvedGeneric)
|
|
299
|
-
const localizedRoute = routeService['createLocalizedRoute'](to, route, 'en')
|
|
300
|
-
expect(localizedRoute).toEqual({
|
|
301
|
-
path: '/invalid-route',
|
|
302
|
-
fullPath: '/invalid-route',
|
|
303
|
-
query: {},
|
|
304
|
-
params: {},
|
|
305
|
-
hash: '',
|
|
306
|
-
})
|
|
307
|
-
})
|
|
308
|
-
|
|
309
|
-
test('resolveLocalizedRoute should handle invalid route', () => {
|
|
310
|
-
const to = '/invalid-route'
|
|
311
|
-
mockRouter.resolve.mockReturnValueOnce({
|
|
312
|
-
fullPath: '/invalid-route',
|
|
313
|
-
path: '/invalid-route',
|
|
314
|
-
query: {},
|
|
315
|
-
hash: '',
|
|
316
|
-
params: {},
|
|
317
|
-
} as RouteLocationResolvedGeneric)
|
|
318
|
-
const localizedRoute = routeService.resolveLocalizedRoute(to, 'en')
|
|
319
|
-
expect(localizedRoute).toEqual({
|
|
320
|
-
path: '/invalid-route',
|
|
321
|
-
fullPath: '/invalid-route',
|
|
322
|
-
query: {},
|
|
323
|
-
params: {},
|
|
324
|
-
hash: '',
|
|
325
|
-
})
|
|
326
|
-
})
|
|
327
|
-
|
|
328
|
-
test('getCurrentLocale should extract locale from fullPath with query params when route.path is missing', () => {
|
|
329
|
-
mockRouter.currentRoute.value.params = {}
|
|
330
|
-
mockRouter.currentRoute.value.path = '' // Simulate missing path (e.g. error state)
|
|
331
|
-
mockRouter.currentRoute.value.fullPath = '/de?foo=bar&baz=qux' // Fallback uses fullPath
|
|
332
|
-
|
|
333
|
-
// Ensure 'de' is in the config locales for this test
|
|
334
|
-
// (It is already present in mockI18nConfig in beforeEach)
|
|
335
|
-
|
|
336
|
-
const locale = routeService.getCurrentLocale()
|
|
337
|
-
expect(locale).toBe('de')
|
|
338
|
-
})
|
|
339
|
-
|
|
340
|
-
test('getCurrentLocale should extract locale from path with hash', () => {
|
|
341
|
-
mockRouter.currentRoute.value.params = {}
|
|
342
|
-
mockRouter.currentRoute.value.path = ''
|
|
343
|
-
mockRouter.currentRoute.value.fullPath = '/de#section'
|
|
344
|
-
const locale = routeService.getCurrentLocale()
|
|
345
|
-
expect(locale).toBe('de')
|
|
346
|
-
})
|
|
347
|
-
})
|