107 lines
2.7 KiB
TypeScript
107 lines
2.7 KiB
TypeScript
import type { TolgeeStaticData } from '@tolgee/svelte'
|
|
import { env } from '$env/dynamic/private'
|
|
import { loadAsync } from 'jszip'
|
|
|
|
class TranslationCacheItem {
|
|
constructor(
|
|
public translastions: TolgeeStaticData,
|
|
public timestamp: number,
|
|
) {}
|
|
|
|
get isExpired(): boolean {
|
|
const now = Date.now()
|
|
|
|
const TTL = Number(env.TRANSLATION_CACHE_TTL)
|
|
|
|
if (Number.isNaN(TTL)) return false
|
|
|
|
return now - this.timestamp > TTL * 1000
|
|
}
|
|
}
|
|
|
|
class LanguageService {
|
|
protected cache: Record<string, TranslationCacheItem> = {}
|
|
|
|
async getTranslations(
|
|
languageCodes: string[],
|
|
): Promise<Record<string, TolgeeStaticData>> {
|
|
const languageCodesToFetch = new Set<string>()
|
|
|
|
const result: Record<string, TolgeeStaticData> = {}
|
|
|
|
for (const lang of languageCodes) {
|
|
const cacheItem = this.cache[lang]
|
|
|
|
if (!cacheItem || cacheItem.isExpired) {
|
|
languageCodesToFetch.add(lang)
|
|
continue
|
|
}
|
|
|
|
Object.assign(result, { [lang]: cacheItem.translastions })
|
|
}
|
|
|
|
if (languageCodesToFetch.size === 0) {
|
|
return result
|
|
}
|
|
|
|
const freshTranslations = await this.fetchTranslations(
|
|
Array.from(languageCodesToFetch),
|
|
)
|
|
|
|
for (const langKey of Object.keys(freshTranslations)) {
|
|
if (langKey in this.cache) {
|
|
delete this.cache[langKey]
|
|
}
|
|
this.cache[langKey] = new TranslationCacheItem(
|
|
freshTranslations[langKey],
|
|
Date.now(),
|
|
)
|
|
result[langKey] = Object.assign(freshTranslations[langKey])
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
protected async fetchTranslations(languageCodes: string | string[]) {
|
|
const url = new URL(`${env.TOLGEE_API_URL}/v2/projects/2/export`)
|
|
|
|
url.searchParams.append('format', 'JSON')
|
|
url.searchParams.append('zip', 'true')
|
|
url.searchParams.append('supportArrays', 'true')
|
|
|
|
for (const lang of languageCodes) {
|
|
url.searchParams.append('languages', lang)
|
|
}
|
|
|
|
if (!env.TOLGEE_API_KEY) {
|
|
throw new Error('TOLGEE_API_KEY not set')
|
|
}
|
|
|
|
const response = await fetch(url, {
|
|
method: 'GET',
|
|
headers: {
|
|
'X-API-Key': env.TOLGEE_API_KEY,
|
|
Accept: 'application/*',
|
|
},
|
|
})
|
|
|
|
const zippedBuffer = await response.arrayBuffer()
|
|
|
|
const zip = await loadAsync(zippedBuffer)
|
|
|
|
const translations: Record<string, TolgeeStaticData> = {}
|
|
|
|
for (const [filename, file] of Object.entries(zip.files)) {
|
|
if (!file.dir && filename.endsWith('.json')) {
|
|
const content = await file.async('string')
|
|
const locale = filename.replace('.json', '')
|
|
translations[locale] = JSON.parse(content)
|
|
}
|
|
}
|
|
|
|
return translations
|
|
}
|
|
}
|
|
|
|
export const languageService = new LanguageService()
|