Skip to content

Commit 0017bed

Browse files
committed
feat(pluralization): enhance handling of empty and undefined forms
1 parent c8eb285 commit 0017bed

6 files changed

Lines changed: 43 additions & 15 deletions

File tree

playground/nuxt.config.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,10 @@ export default defineNuxtConfig({
8787
return null
8888
}
8989
const forms = translation.toString().split('|')
90-
return (count < forms.length ? forms[count].trim() : forms[forms.length - 1].trim()).replace('{count}', count.toString())
90+
if (forms.length === 0) return null
91+
const selectedForm = count < forms.length ? forms[count] : forms[forms.length - 1]
92+
if (!selectedForm) return null
93+
return selectedForm.trim().replace('{count}', count.toString())
9194
},
9295
},
9396
})

playground/pages/page.vue

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,11 +143,18 @@ const customPluralRule = (key: string, count: number, params: Params, _locale: s
143143
}
144144
const forms = translation.toString().split('|')
145145
if (count === 0 && forms.length > 2) {
146-
return forms[0].trim() // Case for "no apples"
146+
const form = forms[0]
147+
return form ? form.trim() : null // Case for "no apples"
147148
}
148149
if (count === 1 && forms.length > 1) {
149-
return forms[1].trim() // Case for "one apple"
150+
const form = forms[1]
151+
return form ? form.trim() : null // Case for "one apple"
150152
}
151-
return (forms.length > 2 ? forms[2].trim() : forms[forms.length - 1].trim()).replace('{count}', count.toString())
153+
if (forms.length > 2) {
154+
const form = forms[2]
155+
return form ? form.trim().replace('{count}', count.toString()) : null
156+
}
157+
const lastForm = forms[forms.length - 1]
158+
return lastForm ? lastForm.trim().replace('{count}', count.toString()) : null
152159
}
153160
</script>

src/module.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,10 @@ export default defineNuxtModule<ModuleOptions>({
100100
return null
101101
}
102102
const forms = translation.toString().split('|')
103-
return (count < forms.length ? forms[count].trim() : forms[forms.length - 1].trim()).replace('{count}', count.toString())
103+
if (forms.length === 0) return null
104+
const selectedForm = count < forms.length ? forms[count] : forms[forms.length - 1]
105+
if (!selectedForm) return null
106+
return selectedForm.trim().replace('{count}', count.toString())
104107
},
105108
customRegexMatcher: undefined,
106109
},
@@ -284,7 +287,9 @@ export default defineNuxtModule<ModuleOptions>({
284287
pages.push(fallbackRoute)
285288
}
286289
if (!isNoPrefixStrategy(options.strategy!)) {
287-
nuxt.options.generate.routes = Array.isArray(nuxt.options.generate.routes) ? nuxt.options.generate.routes : []
290+
// @ts-ignore - generate может не существовать в новых версиях Nuxt
291+
;(nuxt.options as any).generate = (nuxt.options as any).generate || {}
292+
;(nuxt.options as any).generate.routes = Array.isArray((nuxt.options as any).generate.routes) ? (nuxt.options as any).generate.routes : []
288293

289294
if (isCloudflarePages) {
290295
const processPageWithChildren = (page: NuxtPage, parentPath = '') => {
@@ -307,7 +312,7 @@ export default defineNuxtModule<ModuleOptions>({
307312
// Проверяем наличие динамического сегмента :locale
308313
const localeSegmentMatch = fullPath.match(/:locale\(([^)]+)\)/)
309314

310-
if (localeSegmentMatch) {
315+
if (localeSegmentMatch && localeSegmentMatch[1]) {
311316
const availableLocales = localeSegmentMatch[1].split('|') // Достаем локали из сегмента, например "de|ru|en"
312317
localeManager.locales.forEach((locale) => {
313318
const localeCode = locale.code
@@ -347,7 +352,7 @@ export default defineNuxtModule<ModuleOptions>({
347352
}
348353

349354
// Пройдемся по страницам и добавим пути для каждого локализованного пути
350-
pages.forEach((page) => {
355+
pages.forEach((page: NuxtPage) => {
351356
processPageWithChildren(page) // Обрабатываем каждую страницу рекурсивно
352357
})
353358
}
@@ -427,15 +432,17 @@ export default defineNuxtModule<ModuleOptions>({
427432

428433
const routes = nitroConfig.prerender?.routes || []
429434

430-
nuxt.options.generate.routes = Array.isArray(nuxt.options.generate.routes) ? nuxt.options.generate.routes : []
431-
const pages = nuxt.options.generate.routes || []
435+
// @ts-ignore - generate может не существовать в новых версиях Nuxt
436+
;(nuxt.options as any).generate = (nuxt.options as any).generate || {}
437+
;(nuxt.options as any).generate.routes = Array.isArray((nuxt.options as any).generate.routes) ? (nuxt.options as any).generate.routes : []
438+
const pages = (nuxt.options as any).generate.routes || []
432439

433440
localeManager.locales.forEach((locale) => {
434441
// Для стратегий prefix и prefix_and_default генерируем маршруты и для defaultLocale
435442
// Для стратегии prefix_except_default пропускаем defaultLocale
436443
const shouldGenerate = locale.code !== defaultLocale || withPrefixStrategy(options.strategy!)
437444
if (shouldGenerate) {
438-
pages.forEach((page) => {
445+
pages.forEach((page: string) => {
439446
// Пропускаем файлоподобные пути и служебные сегменты `__*`
440447
if (!/\.[a-z0-9]+$/i.test(page) && !isInternalPath(page)) {
441448
const localizedPage = `/${locale.code}${page}`

src/page-manager.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ export class PageManager {
9393
// remove default routes
9494
for (let i = pages.length - 1; i >= 0; i--) {
9595
const page = pages[i]
96+
if (!page) continue
9697
const pagePath = page.path ?? ''
9798
const pageName = page.name ?? ''
9899

@@ -437,7 +438,10 @@ export class PageManager {
437438
): NuxtPage | null {
438439
const routePath = this.buildRoutePath(localeCodes, page.path, encodeURI(customPath), isCustom, customRegex, force)
439440
if (!routePath || routePath == page.path) return null
440-
const routeName = buildRouteName(buildRouteNameFromRoute(page.name, page.path), localeCodes[0], isCustom)
441+
if (localeCodes.length === 0) return null
442+
const firstLocale = localeCodes[0]
443+
if (!firstLocale) return null
444+
const routeName = buildRouteName(buildRouteNameFromRoute(page.name ?? '', page.path ?? ''), firstLocale, isCustom)
441445

442446
return {
443447
...page,

src/runtime/plugins/01.plugin.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,11 @@ export default defineNuxtPlugin(async (nuxtApp) => {
5454
try {
5555
if (!i18nHelper.hasPageTranslation(locale, routeName)) {
5656
let fRouteName = routeName
57-
if (i18nConfig.routesLocaleLinks && i18nConfig.routesLocaleLinks[fRouteName]) {
58-
fRouteName = i18nConfig.routesLocaleLinks[fRouteName]
57+
if (i18nConfig.routesLocaleLinks && fRouteName && i18nConfig.routesLocaleLinks[fRouteName]) {
58+
const newRouteName = i18nConfig.routesLocaleLinks[fRouteName]
59+
if (newRouteName) {
60+
fRouteName = newRouteName
61+
}
5962
}
6063

6164
if (!fRouteName || fRouteName === '') {
@@ -167,6 +170,7 @@ export default defineNuxtPlugin(async (nuxtApp) => {
167170
const currentLocale = routeService.getCurrentLocale()
168171
const { count, ..._params } = typeof params === 'number' ? { count: params } : params
169172

173+
if (count === undefined) return defaultValue ?? key
170174
return plural(key, Number.parseInt(count.toString()), _params, currentLocale, provideData.t) as string ?? defaultValue ?? key
171175
},
172176
tn: (value: number, options?: Intl.NumberFormatOptions) => {

src/runtime/plugins/04.auto-detect.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ import { defineNuxtPlugin, useCookie, useRequestHeaders, navigateTo, useRoute, u
55
const parseAcceptLanguage = (acceptLanguage: string) =>
66
acceptLanguage
77
.split(',')
8-
.map(entry => entry.split(';')[0].trim())
8+
.map((entry) => {
9+
const parts = entry.split(';')
10+
return parts[0] ? parts[0].trim() : ''
11+
})
912

1013
export default defineNuxtPlugin(async (nuxtApp) => {
1114
const i18nConfig = nuxtApp.$config.public.i18nConfig as unknown as ModuleOptionsExtend

0 commit comments

Comments
 (0)