fix: translation
This commit is contained in:
103
src/lib/server/LanguageService.ts
Normal file
103
src/lib/server/LanguageService.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
import type { TolgeeStaticData } from '@tolgee/svelte'
|
||||
import { env } from '$env/dynamic/private'
|
||||
import { TOLGEE_API_KEY, TOLGEE_API_URL } from '$env/static/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.PRIVATE_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(`${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)
|
||||
}
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'X-API-Key': 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()
|
||||
7
src/routes/+layout.server.ts
Normal file
7
src/routes/+layout.server.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { languageService } from '$lib/server/LanguageService'
|
||||
import type { LayoutServerLoad } from './$types'
|
||||
|
||||
export const load: LayoutServerLoad = async () => {
|
||||
const translations = await languageService.getTranslations(['de'])
|
||||
return translations
|
||||
}
|
||||
@@ -6,8 +6,25 @@
|
||||
Tolgee,
|
||||
DevTools,
|
||||
FormatSimple,
|
||||
type TolgeeStaticData,
|
||||
} from '@tolgee/svelte'
|
||||
import { TopBar } from '$lib/components/ui/topBar'
|
||||
import {
|
||||
PUBLIC_TOLGEE_API_KEY,
|
||||
PUBLIC_TOLGEE_API_URL,
|
||||
} from '$env/static/public'
|
||||
import type { Snippet } from 'svelte'
|
||||
|
||||
let { children, data }: { data: TolgeeStaticData; children: Snippet } =
|
||||
$props()
|
||||
|
||||
function getLang(lang: string) {
|
||||
return async (): Promise<Record<string, any>> => {
|
||||
const res = await fetch(`/lang/${lang}`)
|
||||
const translations = await res.json()
|
||||
return translations
|
||||
}
|
||||
}
|
||||
|
||||
const tolgee = Tolgee()
|
||||
.use(DevTools())
|
||||
@@ -15,15 +32,15 @@
|
||||
.init({
|
||||
language: 'de',
|
||||
|
||||
// for development
|
||||
apiUrl: import.meta.env.VITE_TOLGEE_API_URL,
|
||||
apiKey: import.meta.env.VITE_TOLGEE_API_KEY,
|
||||
// // for development
|
||||
// apiUrl: PUBLIC_TOLGEE_API_URL,
|
||||
// apiKey: PUBLIC_TOLGEE_API_KEY,
|
||||
|
||||
// for production
|
||||
staticData: {},
|
||||
staticData: {
|
||||
de: data['de'] ?? getLang('de'),
|
||||
},
|
||||
})
|
||||
|
||||
let { children } = $props()
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
|
||||
10
src/routes/lang/[language]/+server.ts
Normal file
10
src/routes/lang/[language]/+server.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { json } from '@sveltejs/kit'
|
||||
import { languageService } from '$lib/server/LanguageService.js'
|
||||
|
||||
export async function GET({ params }) {
|
||||
const { language } = params
|
||||
|
||||
const result = await languageService.getTranslations([language])
|
||||
|
||||
return json(result[language])
|
||||
}
|
||||
Reference in New Issue
Block a user