1
0
Fork 0
mirror of https://github.com/Chocobozzz/PeerTube.git synced 2025-10-03 09:49:20 +02:00
Peertube/server/core/helpers/i18n.ts
Chocobozzz d6e4dac032
Add email translations
Convert emails from Pug template to Handlebars because i18next doesn't
support Pug
2025-07-24 09:18:04 +02:00

76 lines
2.6 KiB
TypeScript

import { AVAILABLE_LOCALES, getCompleteLocale } from '@peertube/peertube-core-utils'
import { CONFIG } from '@server/initializers/config.js'
import { LANGUAGE_COOKIE_NAME, LANGUAGE_HEADER, SERVER_INTERNAL_LOCALES_BASE_PATH } from '@server/initializers/constants.js'
import { MUser } from '@server/types/models/index.js'
import Bluebird from 'bluebird'
import express from 'express'
import { readJson } from 'fs-extra/esm'
import { readdir } from 'fs/promises'
import i18next from 'i18next'
import ICU from 'i18next-icu'
import { join } from 'path'
import { logger } from './logger.js'
export async function initI18n () {
const locales = await readdir(SERVER_INTERNAL_LOCALES_BASE_PATH)
const resources: Record<string, Record<string, string>> = {}
await Bluebird.map(locales, async locale => {
const localePath = join(SERVER_INTERNAL_LOCALES_BASE_PATH, locale)
const translation = await readJson(join(localePath, 'translation.json'))
resources[locale] = { translation }
}, { concurrency: 10 })
return i18next.use(ICU)
.init({
resources,
nsSeparator: false,
keySeparator: false,
// do not load a fallback
fallbackLng: false
})
.then(() => logger.info('i18n initialized with locales: ' + Object.keys(resources).join(', ')))
}
export function useI18n (req: express.Request, res: express.Response, next: express.NextFunction) {
req.t = (key: string, context: Record<string, string | number> = {}) => {
// Use req special header language
// Or user language
// Or default language
const language = req.headers[LANGUAGE_HEADER] as string ||
res.locals.oauth?.token?.User?.language ||
req.acceptsLanguages(AVAILABLE_LOCALES) ||
CONFIG.INSTANCE.DEFAULT_LANGUAGE
return t(key, language, context)
}
next()
}
export function t (key: string, language: string, context: Record<string, string | number> = {}) {
if (!language) throw new Error('Language is required for translation')
return i18next.t(key, { lng: getCompleteLocale(language), ...context })
}
export function tu (key: string, user: Pick<MUser, 'language' | 'getLanguage'>, context: Record<string, string | number> = {}) {
return t(key, user.getLanguage(), context)
}
// ---------------------------------------------------------------------------
export function setClientLanguageCookie (res: express.Response, language: string) {
if (language === null) {
res.clearCookie(LANGUAGE_COOKIE_NAME)
return
}
res.cookie(LANGUAGE_COOKIE_NAME, language, {
secure: true,
sameSite: 'none',
maxAge: 1000 * 3600 * 24 * 90 // 3 months
})
}