2022-11-07 00:56:44 +01:00
|
|
|
import Vue from "vue"
|
2022-11-09 00:10:08 +01:00
|
|
|
import enUsStrings from '../strings/en-us.json'
|
2022-11-09 01:09:07 +01:00
|
|
|
import { supplant } from './utils'
|
2022-11-07 00:56:44 +01:00
|
|
|
|
|
|
|
const defaultCode = 'en-us'
|
|
|
|
|
2022-11-09 01:09:07 +01:00
|
|
|
const languageCodeMap = {
|
2024-04-10 19:46:39 +02:00
|
|
|
'bn': { label: 'বাংলা', dateFnsLocale: 'bn' },
|
2023-11-01 21:42:54 +01:00
|
|
|
'cs': { label: 'Čeština', dateFnsLocale: 'cs' },
|
2023-10-15 15:23:22 +02:00
|
|
|
'da': { label: 'Dansk', dateFnsLocale: 'da' },
|
2023-01-30 15:07:36 +01:00
|
|
|
'de': { label: 'Deutsch', dateFnsLocale: 'de' },
|
|
|
|
'en-us': { label: 'English', dateFnsLocale: 'enUS' },
|
2023-03-07 16:37:55 +01:00
|
|
|
'es': { label: 'Español', dateFnsLocale: 'es' },
|
2024-02-22 08:46:09 +01:00
|
|
|
'et': { label: 'Eesti', dateFnsLocale: 'et' },
|
2023-01-30 15:07:36 +01:00
|
|
|
'fr': { label: 'Français', dateFnsLocale: 'fr' },
|
2024-03-16 18:26:22 +01:00
|
|
|
'he': { label: 'עברית', dateFnsLocale: 'he' },
|
2023-01-30 15:07:36 +01:00
|
|
|
'hr': { label: 'Hrvatski', dateFnsLocale: 'hr' },
|
|
|
|
'it': { label: 'Italiano', dateFnsLocale: 'it' },
|
2023-07-25 21:13:43 +02:00
|
|
|
'lt': { label: 'Lietuvių', dateFnsLocale: 'lt' },
|
2024-02-20 12:25:43 +01:00
|
|
|
'hu': { label: 'Magyar', dateFnsLocale: 'hu' },
|
2023-05-03 14:52:32 +02:00
|
|
|
'nl': { label: 'Nederlands', dateFnsLocale: 'nl' },
|
2023-09-23 16:18:48 +02:00
|
|
|
'no': { label: 'Norsk', dateFnsLocale: 'no' },
|
2023-01-30 15:07:36 +01:00
|
|
|
'pl': { label: 'Polski', dateFnsLocale: 'pl' },
|
2024-02-16 15:57:54 +01:00
|
|
|
'pt-br': { label: 'Português (Brasil)', dateFnsLocale: 'ptBR' },
|
2023-02-03 21:08:38 +01:00
|
|
|
'ru': { label: 'Русский', dateFnsLocale: 'ru' },
|
2023-11-05 17:16:40 +01:00
|
|
|
'sv': { label: 'Svenska', dateFnsLocale: 'sv' },
|
2024-03-19 22:18:34 +01:00
|
|
|
'uk': { label: 'Українська', dateFnsLocale: 'uk' },
|
2024-03-10 03:09:08 +01:00
|
|
|
'vi-vn': { label: 'Tiếng Việt', dateFnsLocale: 'vi' },
|
2023-01-30 15:42:56 +01:00
|
|
|
'zh-cn': { label: '简体中文 (Simplified Chinese)', dateFnsLocale: 'zhCN' },
|
2024-03-18 01:19:52 +01:00
|
|
|
'zh-tw': { label: '正體中文 (Traditional Chinese)', dateFnsLocale: 'zhTW' }
|
2022-11-09 01:09:07 +01:00
|
|
|
}
|
|
|
|
Vue.prototype.$languageCodeOptions = Object.keys(languageCodeMap).map(code => {
|
|
|
|
return {
|
2023-01-30 15:07:36 +01:00
|
|
|
text: languageCodeMap[code].label,
|
2022-11-09 01:09:07 +01:00
|
|
|
value: code
|
|
|
|
}
|
|
|
|
})
|
2024-02-17 20:24:49 +01:00
|
|
|
|
|
|
|
// iTunes search API uses ISO 3166 country codes: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
|
2024-01-04 04:52:45 +01:00
|
|
|
const podcastSearchRegionMap = {
|
2024-04-24 13:51:38 +02:00
|
|
|
'br': { label: 'Brasil' },
|
|
|
|
'be': { label: 'België / Belgique / Belgien' },
|
|
|
|
'cz': { label: 'Česko' },
|
|
|
|
'dk': { label: 'Danmark' },
|
|
|
|
'de': { label: 'Deutschland' },
|
|
|
|
'ee': { label: 'Eesti' },
|
|
|
|
'es': { label: 'España / Espanya / Espainia' },
|
|
|
|
'fr': { label: 'France' },
|
|
|
|
'hr': { label: 'Hrvatska' },
|
|
|
|
'il': { label: 'ישראל / إسرائيل' },
|
|
|
|
'it': { label: 'Italia' },
|
|
|
|
'lu': { label: 'Luxembourg / Luxemburg / Lëtezebuerg' },
|
2024-04-24 13:57:51 +02:00
|
|
|
'hu': { label: 'Magyarország' },
|
2024-04-24 13:51:38 +02:00
|
|
|
'nl': { label: 'Nederland' },
|
|
|
|
'no': { label: 'Norge' },
|
2024-04-24 13:57:51 +02:00
|
|
|
'at': { label: 'Österreich' },
|
2024-04-24 13:51:38 +02:00
|
|
|
'pl': { label: 'Polska' },
|
|
|
|
'pt': { label: 'Portugal' },
|
|
|
|
'ru': { label: 'Россия' },
|
2024-04-24 13:57:51 +02:00
|
|
|
'ch': { label: 'Schweiz / Suisse / Svizzera' },
|
2024-04-24 13:51:38 +02:00
|
|
|
'se': { label: 'Sverige' },
|
|
|
|
'vn': { label: 'Việt Nam' },
|
2024-03-19 22:18:34 +01:00
|
|
|
'ua': { label: 'Україна' },
|
2024-04-24 13:51:38 +02:00
|
|
|
'gb': { label: 'United Kingdom' },
|
2024-01-04 04:52:45 +01:00
|
|
|
'us': { label: 'United States' },
|
2024-02-17 20:24:49 +01:00
|
|
|
'cn': { label: '中国' }
|
2024-01-04 04:52:45 +01:00
|
|
|
}
|
|
|
|
Vue.prototype.$podcastSearchRegionOptions = Object.keys(podcastSearchRegionMap).map(code => {
|
|
|
|
return {
|
|
|
|
text: podcastSearchRegionMap[code].label,
|
|
|
|
value: code
|
|
|
|
}
|
|
|
|
})
|
2022-11-09 01:09:07 +01:00
|
|
|
|
|
|
|
Vue.prototype.$languageCodes = {
|
2024-04-19 00:06:12 +02:00
|
|
|
default: defaultCode, // en-us
|
|
|
|
current: defaultCode, // Current language code in use
|
|
|
|
local: null, // Language code set at user level
|
|
|
|
server: null // Language code set at server level
|
2022-11-08 01:27:17 +01:00
|
|
|
}
|
|
|
|
|
2024-04-19 00:06:12 +02:00
|
|
|
// Currently loaded strings (default enUS)
|
2022-11-09 01:09:07 +01:00
|
|
|
Vue.prototype.$strings = { ...enUsStrings }
|
2022-11-10 01:00:20 +01:00
|
|
|
|
2024-04-19 00:06:12 +02:00
|
|
|
/**
|
|
|
|
* Get string and substitute
|
|
|
|
*
|
|
|
|
* @param {string} key
|
|
|
|
* @param {string[]} subs
|
|
|
|
* @returns {string}
|
|
|
|
*/
|
2022-11-08 01:27:17 +01:00
|
|
|
Vue.prototype.$getString = (key, subs) => {
|
|
|
|
if (!Vue.prototype.$strings[key]) return ''
|
2023-07-01 00:30:15 +02:00
|
|
|
if (subs?.length && Array.isArray(subs)) {
|
2022-11-08 01:27:17 +01:00
|
|
|
return supplant(Vue.prototype.$strings[key], subs)
|
|
|
|
}
|
|
|
|
return Vue.prototype.$strings[key]
|
|
|
|
}
|
2022-11-07 00:56:44 +01:00
|
|
|
|
2024-04-19 00:30:06 +02:00
|
|
|
Vue.prototype.$formatNumber = (num) => {
|
|
|
|
return Intl.NumberFormat(Vue.prototype.$languageCodes.current).format(num)
|
|
|
|
}
|
|
|
|
|
2024-04-19 00:06:12 +02:00
|
|
|
const translations = {
|
2022-11-09 00:10:08 +01:00
|
|
|
[defaultCode]: enUsStrings
|
|
|
|
}
|
2022-11-07 00:56:44 +01:00
|
|
|
|
|
|
|
function loadTranslationStrings(code) {
|
|
|
|
return new Promise((resolve) => {
|
|
|
|
import(`../strings/${code}`).then((fileContents) => {
|
|
|
|
resolve(fileContents.default)
|
|
|
|
}).catch((error) => {
|
|
|
|
console.error('Failed to load i18n strings', code, error)
|
2022-11-09 00:10:08 +01:00
|
|
|
resolve(null)
|
2022-11-07 00:56:44 +01:00
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
async function loadi18n(code) {
|
2022-11-09 01:09:07 +01:00
|
|
|
if (!code) return false
|
|
|
|
if (Vue.prototype.$languageCodes.current == code) {
|
2022-11-07 00:56:44 +01:00
|
|
|
// already set
|
2022-11-09 01:09:07 +01:00
|
|
|
return false
|
2022-11-07 00:56:44 +01:00
|
|
|
}
|
2022-11-09 01:09:07 +01:00
|
|
|
|
2022-11-07 00:56:44 +01:00
|
|
|
const strings = translations[code] || await loadTranslationStrings(code)
|
2022-11-09 00:10:08 +01:00
|
|
|
if (!strings) {
|
|
|
|
console.warn(`Invalid lang code ${code}`)
|
2022-11-09 01:09:07 +01:00
|
|
|
return false
|
2022-11-09 00:10:08 +01:00
|
|
|
}
|
2022-11-07 00:56:44 +01:00
|
|
|
|
|
|
|
translations[code] = strings
|
2022-11-09 01:09:07 +01:00
|
|
|
Vue.prototype.$languageCodes.current = code
|
|
|
|
localStorage.setItem('lang', code)
|
2022-11-07 00:56:44 +01:00
|
|
|
|
|
|
|
for (const key in Vue.prototype.$strings) {
|
|
|
|
Vue.prototype.$strings[key] = strings[key] || translations[defaultCode][key]
|
|
|
|
}
|
2023-05-03 14:52:32 +02:00
|
|
|
|
2023-01-30 15:07:36 +01:00
|
|
|
Vue.prototype.$setDateFnsLocale(languageCodeMap[code].dateFnsLocale)
|
2022-11-09 01:09:07 +01:00
|
|
|
|
2024-02-16 16:12:47 +01:00
|
|
|
this?.$eventBus?.$emit('change-lang', code)
|
2022-11-09 01:09:07 +01:00
|
|
|
return true
|
2022-11-07 00:56:44 +01:00
|
|
|
}
|
|
|
|
|
2022-11-09 01:09:07 +01:00
|
|
|
Vue.prototype.$setLanguageCode = loadi18n
|
|
|
|
|
|
|
|
// Set the servers default language code, does not override users local language code
|
|
|
|
Vue.prototype.$setServerLanguageCode = (code) => {
|
|
|
|
if (!code) return
|
|
|
|
|
|
|
|
if (!languageCodeMap[code]) {
|
|
|
|
console.warn('invalid server language in', code)
|
|
|
|
} else {
|
|
|
|
Vue.prototype.$languageCodes.server = code
|
|
|
|
if (!Vue.prototype.$languageCodes.local && code !== defaultCode) {
|
|
|
|
loadi18n(code)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize with language code in localStorage if valid
|
|
|
|
async function initialize() {
|
|
|
|
const localLanguage = localStorage.getItem('lang')
|
|
|
|
if (!localLanguage) return
|
|
|
|
|
|
|
|
if (!languageCodeMap[localLanguage]) {
|
|
|
|
console.warn('Invalid local language code', localLanguage)
|
|
|
|
localStorage.setItem('lang', defaultCode)
|
2022-11-10 01:00:20 +01:00
|
|
|
} else {
|
2022-11-09 01:09:07 +01:00
|
|
|
Vue.prototype.$languageCodes.local = localLanguage
|
|
|
|
loadi18n(localLanguage)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
initialize()
|
2022-11-07 00:56:44 +01:00
|
|
|
|