Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions src-tauri/locales/pt-PT.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"tray": {
"quit": "Sair",
"showOrHide": "Mostrar/Ocultar janela",
"addToQueue": "Adicionar da área de transferência",
"downloadQueue": "Transferir fila",
"shortcuts": {
"ctrlShiftV": "Ctrl + Shift + V",
"ctrlShiftEnter": "Ctrl + Shift + Enter",
"altShiftV": "Alt + Shift + V",
"altShiftEnter": "Alt + Shift + Enter"
}
},
"notifications": {
"queueAdded": {
"title": "Adicionado à fila",
"body": "{title}"
},
"queueDownloading": {
"title": "A transferir a fila",
"body": "A transferir {n} item | A transferir {n} itens"
},
"queueFinished": {
"title": "Fila concluída",
"body": "Transferência de {n} item concluída | Transferência de {n} itens concluída"
},
"videoFinished": {
"title": "Transferência concluída",
"body": "{title}"
},
"playlistFinished": {
"title": "Playlist concluída",
"body": "{title}"
},
"videoReady": {
"title": "Pronto a transferir",
"body": "{title}"
},
"playlistReady": {
"title": "Playlist pronta a transferir",
"body": "{title} | {title} ({n} item) | {title} ({n} itens)"
},
"downloadFailed": {
"title": "Falha na transferência",
"body": "{title}\n{message}"
}
}
}
35 changes: 23 additions & 12 deletions src/helpers/subtitles/languages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,21 @@ export interface SubtitleLanguageOption {
}

const codes = ISO6391.getAllCodes();
const expanded_codes: Record<string, SubtitleLanguageOption> = {

const expandedCodes: Record<string, SubtitleLanguageOption> = {
'pt-PT': { code: 'pt-PT', englishName: 'Portuguese (Portugal)', nativeName: 'Português (Portugal)' },
'pt-BR': { code: 'pt-BR', englishName: 'Portuguese (Brazil)', nativeName: 'Português (Brasil)' },
'zh-TW': { code: 'zh-TW', englishName: 'Traditional Chinese (Taiwan)', nativeName: '繁體中文(台灣)' },
};

export const languageOptions: SubtitleLanguageOption[] = [...codes, ...Object.keys(expanded_codes)]
export const languageOptions: SubtitleLanguageOption[] = [...codes, ...Object.keys(expandedCodes)]
.map((code) => {
if (expanded_codes[code]) return expanded_codes[code];

const englishName = ISO6391.getName(code);
const nativeName = ISO6391.getNativeName(code);
if (expandedCodes[code]) return expandedCodes[code];

return {
code,
englishName,
nativeName,
englishName: ISO6391.getName(code),
nativeName: ISO6391.getNativeName(code),
};
})
.sort((a, b) => a.englishName.localeCompare(b.englishName));
Expand All @@ -31,20 +30,32 @@ export const languageOptionsLookup = new Map(
languageOptions.map(option => [option.code, option] as const),
);

function normalizeLocale(candidate: string): string {
const parts = candidate.replace(/_/g, '-').split('-');
const language = parts[0]?.toLowerCase();
const region = parts[1]?.toUpperCase();

return region ? `${language}-${region}` : language;
}

export function detectBrowserLanguageCodes(): string[] {
let candidates = navigator?.languages ?? [];
if (candidates.length === 0) {
if (candidates.length === 0 && navigator?.language) {
candidates = [navigator.language];
}

const normalized = new Set<string>();

for (const candidate of candidates ?? []) {
if (!candidate) {
continue;
if (!candidate) continue;

const locale = normalizeLocale(candidate);

if (expandedCodes[locale]) {
normalized.add(locale);
}

const isoCode = candidate.split('-')[0]?.toLowerCase();
const isoCode = locale.split('-')[0];
if (isoCode && ISO6391.validate(isoCode)) {
normalized.add(isoCode);
}
Expand Down
77 changes: 58 additions & 19 deletions src/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createI18n, I18n } from 'vue-i18n';
import { createI18n } from 'vue-i18n';
import en from './locales/en.json';
import es from './locales/es.json';
import nl from './locales/nl.json';
Expand All @@ -8,41 +8,80 @@
import nb from './locales/nb.json';
import ru from './locales/ru.json';
import tr from './locales/tr.json';
import ptPT from './locales/pt-PT.json';
import ptBR from './locales/pt-BR.json';
import zhTW from './locales/zh-TW.json';
import { detectBrowserLanguageCodes } from './helpers/subtitles/languages.ts';

export const availableLocales: Record<string, boolean> = {
'en': true, 'es': true, 'nl': true, 'it': true, 'fr': true, 'de': true, 'nb': true, 'ru': true, 'tr': true, 'pt-BR': true, 'zh-TW': true,
export const availableLocales = {
'en': true,
'es': true,
'nl': true,
'it': true,
'fr': true,
'de': true,
'nb': true,
'ru': true,
'tr': true,
'pt-PT': true,
'pt-BR': true,
'zh-TW': true,
} as const;

type MessageSchema = typeof en;
export type Locale = keyof typeof availableLocales;

export function getDefaultLocale() {
const browserLocale = detectBrowserLanguageCodes()[0];
if (availableLocales[browserLocale]) {
return browserLocale;
const localeAliases: Record<string, Locale> = {
'pt': 'pt-PT',
'pt-PT': 'pt-PT',
'pt-BR': 'pt-BR',
'zh': 'zh-TW',
'zh-Hant': 'zh-TW',
'zh-TW': 'zh-TW',
'no': 'nb',
'nb-NO': 'nb',
};

export function getDefaultLocale(): Locale {
for (const code of detectBrowserLanguageCodes()) {
if (code in availableLocales) {
return code as Locale;
}

if (code in localeAliases) {
return localeAliases[code];
}

const baseCode = code.split('-')[0];
if (baseCode in availableLocales) {
return baseCode as Locale;
}

if (baseCode in localeAliases) {
return localeAliases[baseCode];
}
}

return 'en';
}

export const i18n: I18n = createI18n<[MessageSchema], Locale>({
locale: 'en',
export const i18n = createI18n<[MessageSchema], Locale>({
locale: getDefaultLocale(),
legacy: false,
globalInjection: false,
fallbackLocale: 'en',
messages: {
en,
es,
nl,
it,
fr,
de,
nb,
ru,
tr,
'en': en,
'es': es,
'nl': nl,
'it': it,
'fr': fr,
'de': de,
'nb': nb,
'ru': ru,
'tr': tr,
'pt-PT': ptPT,
'pt-BR': ptBR,
'zh-TW': zhTW,
},
});
});

Check failure on line 87 in src/i18n.ts

View workflow job for this annotation

GitHub Actions / Lint

Newline required at end of file but not found
Loading
Loading