Skip to content

Commit

Permalink
test(app): start of a test to validate translation mappings
Browse files Browse the repository at this point in the history
  • Loading branch information
y3rsh committed Dec 12, 2024
1 parent 3809a79 commit 8674a59
Showing 1 changed file with 88 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { resources } from '..'
import { describe, it, expect } from 'vitest'

Check failure on line 2 in app/src/assets/localization/__tests__/translationConsistency.test.ts

View workflow job for this annotation

GitHub Actions / js checks

'expect' is defined but never used

Check failure on line 2 in app/src/assets/localization/__tests__/translationConsistency.test.ts

View workflow job for this annotation

GitHub Actions / js checks

'expect' is defined but never used

describe('Translation consistency between en and zh', () => {
const enTranslations = resources['en']

Check failure on line 5 in app/src/assets/localization/__tests__/translationConsistency.test.ts

View workflow job for this annotation

GitHub Actions / js checks

["en"] is better written in dot notation

Check failure on line 5 in app/src/assets/localization/__tests__/translationConsistency.test.ts

View workflow job for this annotation

GitHub Actions / js checks

["en"] is better written in dot notation
const zhTranslations = resources['zh']

Check failure on line 6 in app/src/assets/localization/__tests__/translationConsistency.test.ts

View workflow job for this annotation

GitHub Actions / js checks

["zh"] is better written in dot notation

Check failure on line 6 in app/src/assets/localization/__tests__/translationConsistency.test.ts

View workflow job for this annotation

GitHub Actions / js checks

["zh"] is better written in dot notation

const checkKeys = (
base: { [key: string]: any },
compare: { [key: string]: any },
baseLang: string,
compareLang: string
) => {
const missingKeys: string[] = []

const traverseKeys = (obj: object, path = '') => {
Object.entries(obj).forEach(([key, value]) => {
const fullPath = path ? `${path}.${key}` : key

if (typeof value === 'object' && value !== null) {
// Recursively check nested objects
traverseKeys(value, fullPath)
} else {
// Check if key exists and has same type
const compareObj = path
.split('.')
.reduce((acc, curr) => acc?.[curr], compare)
if (!compareObj?.[key] || typeof compareObj[key] !== typeof value) {
missingKeys.push(fullPath)
}
}
})
}

traverseKeys(base)

if (missingKeys.length > 0) {
throw new Error(
`Missing ${compareLang} translations for the following ${baseLang} keys:\n${missingKeys.join(
'\n'
)}`
)
}
}

it('should have all keys in zh that are in en', () => {
checkKeys(enTranslations, zhTranslations, 'en', 'zh')
})

it('should have all keys in en that are in zh', () => {
checkKeys(zhTranslations, enTranslations, 'zh', 'en')
})

it('should have matching value types', () => {
const checkValueTypes = (
obj1: { [key: string]: any },
obj2: { [key: string]: any },
path = ''
) => {
const typeMismatches: string[] = []

Object.entries(obj1).forEach(([key, value]) => {
const fullPath = path ? `${path}.${key}` : key
const value2 = path
.split('.')
.reduce((acc, curr) => acc?.[curr], obj2)?.[key]

if (value2 !== undefined && typeof value !== typeof value2) {
typeMismatches.push(
`${fullPath}: en(${typeof value}) vs zh(${typeof value2})`
)
}

if (typeof value === 'object' && value !== null) {
checkValueTypes(value, value2, fullPath)
}
})

return typeMismatches
}

const typeMismatches = checkValueTypes(enTranslations, zhTranslations)

if (typeMismatches.length > 0) {
throw new Error(`Type mismatches found:\n${typeMismatches.join('\n')}`)
}
})
})

0 comments on commit 8674a59

Please sign in to comment.