99 lines
2.4 KiB
TypeScript
99 lines
2.4 KiB
TypeScript
import { readFileSync } from 'node:fs'
|
|
import { join } from 'node:path'
|
|
import { describe, expect, it } from 'vitest'
|
|
import { COPY } from '@/lib/directoryCopy'
|
|
import { messages } from './messages'
|
|
|
|
const SOURCES = [
|
|
'components/AuthorAvatar.vue',
|
|
'components/AuthorFormPanel.vue',
|
|
'components/AuthorViewPanel.vue',
|
|
'components/DashboardShell.vue',
|
|
'components/BuilderMoreMenu.vue',
|
|
'components/DeleteTypeDialog.vue',
|
|
'components/DirectoryBadge.vue',
|
|
'components/DirectoryDialog.vue',
|
|
'components/DirectoryField.vue',
|
|
'components/DirectoryList.vue',
|
|
'components/DirectoryPageNotice.vue',
|
|
'components/DirectoryPanel.vue',
|
|
'components/DirectoryRowMenu.vue',
|
|
'components/LinkUserDialog.vue',
|
|
'components/MediaField.vue',
|
|
'components/PublishingLinksCard.vue',
|
|
'components/ReassignDialog.vue',
|
|
'components/SiteFormPanel.vue',
|
|
'components/SitesForbidden.vue',
|
|
'components/SlugField.vue',
|
|
'components/SocialLinksRepeater.vue',
|
|
'components/UserSelect.vue',
|
|
'composables/useDirectoryToasts.ts',
|
|
'composables/useSchemaDelete.ts',
|
|
'composables/useDirectoryView.ts',
|
|
'lib/directory.ts',
|
|
'lib/directoryCopy.ts',
|
|
'lib/directoryRules.ts',
|
|
'lib/schemaEntries.ts',
|
|
'lib/siteTitleTemplate.ts',
|
|
'views/AuthorsView.vue',
|
|
'views/SitesView.vue',
|
|
]
|
|
|
|
const SAME_IN_FRENCH = new Set([
|
|
'Articles',
|
|
'Auto',
|
|
'Cache',
|
|
'Avatar',
|
|
'Bio',
|
|
'Noindex',
|
|
'Site',
|
|
'Sites',
|
|
'1 site',
|
|
'{0} sites',
|
|
'Guest',
|
|
'Linked',
|
|
'Description',
|
|
'Image',
|
|
'Robots',
|
|
])
|
|
|
|
const LITERAL = /\bt\(\s*(?:'((?:\\.|[^'\\])*)'|"((?:\\.|[^"\\])*)")/g
|
|
|
|
function keysIn(source: string) {
|
|
return [...source.matchAll(LITERAL)].map((match) =>
|
|
(match[1] ?? match[2] ?? '').replace(/\\(['"\\])/g, '$1'),
|
|
)
|
|
}
|
|
|
|
describe('Sites and authors messages', () => {
|
|
const keys = SOURCES.flatMap((file) =>
|
|
keysIn(readFileSync(join(import.meta.dirname, '..', file), 'utf8')).map((key) => ({
|
|
file,
|
|
key,
|
|
})),
|
|
)
|
|
|
|
it('finds the strings of both screens', () => {
|
|
expect(keys.length).toBeGreaterThan(100)
|
|
})
|
|
|
|
it.each(keys.map(({ file, key }) => [file, key]))(
|
|
'%s: "%s" has its own French entry',
|
|
(_file, key) => {
|
|
const french = (messages as Record<string, string>)[key as string]
|
|
|
|
expect(french).toMatch(/\S/)
|
|
if (!SAME_IN_FRENCH.has(key as string)) {
|
|
expect(french).not.toBe(key)
|
|
}
|
|
},
|
|
)
|
|
|
|
it.each(Object.values(COPY))('shared copy "%s" has its own French entry', (key) => {
|
|
const french = (messages as Record<string, string>)[key]
|
|
|
|
expect(french).toBeTruthy()
|
|
expect(french).not.toBe(key)
|
|
})
|
|
})
|