feat: multilanguage album type parsing

- new album types: Audiobook, Show
This commit is contained in:
ThetaDev 2022-11-01 18:10:28 +01:00
parent abfd630a04
commit 45e2d3c7c7
15 changed files with 2354 additions and 32 deletions

View file

@ -0,0 +1,121 @@
use std::{collections::BTreeMap, fs::File, io::BufReader, path::Path};
use futures::stream::{self, StreamExt};
use rustypipe::{
client::{ClientType, RustyPipe, RustyPipeQuery, YTContext},
model::AlbumType,
param::{locale::LANGUAGES, Language},
};
use serde::{Deserialize, Serialize};
use crate::util::{self, TextRuns};
pub async fn collect_album_types(project_root: &Path, concurrency: usize) {
let mut json_path = project_root.to_path_buf();
json_path.push("testfiles/dict/album_type_samples.json");
let album_types = [
(AlbumType::Album, "MPREb_nlBWQROfvjo"),
(AlbumType::Single, "MPREb_bHfHGoy7vuv"),
(AlbumType::Ep, "MPREb_u1I69lSAe5v"),
(AlbumType::Audiobook, "MPREb_gaoNzsQHedo"),
(AlbumType::Show, "MPREb_cwzk8EUwypZ"),
];
let rp = RustyPipe::new();
let collected_album_types = stream::iter(LANGUAGES)
.map(|lang| {
let rp = rp.clone();
async move {
let query = rp.query().lang(lang);
let mut data: BTreeMap<AlbumType, String> = BTreeMap::new();
for (album_type, id) in album_types {
let atype_txt = get_album_type(&query, id).await;
println!("collected {}-{:?} ({})", lang, album_type, &atype_txt);
data.insert(album_type, atype_txt);
}
(lang, data)
}
})
.buffer_unordered(concurrency)
.collect::<BTreeMap<_, _>>()
.await;
let file = File::create(json_path).unwrap();
serde_json::to_writer_pretty(file, &collected_album_types).unwrap();
}
pub fn write_samples_to_dict(project_root: &Path) {
let mut json_path = project_root.to_path_buf();
json_path.push("testfiles/dict/album_type_samples.json");
let json_file = File::open(json_path).unwrap();
let collected: BTreeMap<Language, BTreeMap<AlbumType, String>> =
serde_json::from_reader(BufReader::new(json_file)).unwrap();
let mut dict = util::read_dict(project_root);
let langs = dict.keys().map(|k| k.to_owned()).collect::<Vec<_>>();
for lang in langs {
let dict_entry = dict.entry(lang).or_default();
let mut e_langs = dict_entry.equivalent.clone();
e_langs.push(lang);
collected.get(&lang).unwrap().iter().for_each(|(t, v)| {
dict_entry.album_types.insert(v.to_lowercase(), *t);
});
}
util::write_dict(project_root, &dict);
}
#[derive(Debug, Deserialize)]
struct AlbumData {
header: Header,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
struct Header {
music_detail_header_renderer: HeaderRenderer,
}
#[derive(Debug, Deserialize)]
struct HeaderRenderer {
subtitle: TextRuns,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
struct QBrowse<'a> {
context: YTContext<'a>,
browse_id: &'a str,
}
async fn get_album_type(query: &RustyPipeQuery, id: &str) -> String {
let context = query
.get_context(ClientType::DesktopMusic, true, None)
.await;
let body = QBrowse {
context,
browse_id: id,
};
let response_txt = query
.raw(ClientType::DesktopMusic, "browse", &body)
.await
.unwrap();
let album = serde_json::from_str::<AlbumData>(&response_txt).unwrap();
album
.header
.music_detail_header_renderer
.subtitle
.runs
.into_iter()
.next()
.unwrap()
.text
}

View file

@ -375,13 +375,11 @@ async fn get_channel(channel_id: &str, lang: Language) -> Result<ChannelData> {
.iter()
.map(|itm| {
(
util::parse_numeric(
&itm.grid_video_renderer.view_count_text.simple_text,
)
.unwrap(),
util::parse_numeric(&itm.grid_video_renderer.view_count_text.text)
.unwrap(),
itm.grid_video_renderer
.short_view_count_text
.simple_text
.text
.to_owned(),
)
})

View file

@ -36,6 +36,7 @@ pub fn generate_dictionary(project_root: &Path) {
let code_head = r#"// This file is automatically generated. DO NOT EDIT.
// See codegen/gen_dictionary.rs for the generation code.
use crate::{
model::AlbumType,
param::Language,
timeago::{DateCmp, TaToken, TimeUnit},
};
@ -75,6 +76,10 @@ pub(crate) struct Entry {
///
/// Format: Parsed token -> decimal power
pub number_tokens: phf::Map<&'static str, u8>,
/// Names of album types (Album, Single, ...)
///
/// Format: Parsed text -> Album type
pub album_types: phf::Map<&'static str, AlbumType>,
}
"#;
@ -136,13 +141,20 @@ pub(crate) fn entry(lang: Language) -> Entry {
number_tokens.entry(txt, &mag.to_string());
});
// Album types
let mut album_types = phf_codegen::Map::<&str>::new();
entry.album_types.iter().for_each(|(txt, album_type)| {
album_types.entry(txt, &format!("AlbumType::{:?}", album_type));
});
let code_ta_tokens = &ta_tokens.build().to_string().replace('\n', "\n ");
let code_ta_nd_tokens = &ta_nd_tokens.build().to_string().replace('\n', "\n ");
let code_months = &months.build().to_string().replace('\n', "\n ");
let code_number_tokens = &number_tokens.build().to_string().replace('\n', "\n ");
let code_album_types = &album_types.build().to_string().replace('\n', "\n ");
let _ = write!(code_timeago_tokens, "{} => Entry {{\n by_char: {:?},\n timeago_tokens: {},\n date_order: {},\n months: {},\n timeago_nd_tokens: {},\n comma_decimal: {:?},\n number_tokens: {},\n }},\n ",
selector, entry.by_char, code_ta_tokens, date_order, code_months, code_ta_nd_tokens, entry.comma_decimal, code_number_tokens);
let _ = write!(code_timeago_tokens, "{} => Entry {{\n by_char: {:?},\n timeago_tokens: {},\n date_order: {},\n months: {},\n timeago_nd_tokens: {},\n comma_decimal: {:?},\n number_tokens: {},\n album_types: {},\n }},\n ",
selector, entry.by_char, code_ta_tokens, date_order, code_months, code_ta_nd_tokens, entry.comma_decimal, code_number_tokens, code_album_types);
});
code_timeago_tokens = code_timeago_tokens.trim_end().to_owned() + "\n }\n}\n";

View file

@ -359,7 +359,7 @@ fn map_language_section(section: &CompactLinkRendererWrap) -> BTreeMap<String, S
.select_language_command
.hl
.to_owned(),
i.compact_link_renderer.title.simple_text.to_owned(),
i.compact_link_renderer.title.text.to_owned(),
)
})
.collect()

View file

@ -1,3 +1,4 @@
mod collect_album_types;
mod collect_large_numbers;
mod collect_playlist_dates;
mod download_testfiles;
@ -23,8 +24,10 @@ struct Cli {
enum Commands {
CollectPlaylistDates,
CollectLargeNumbers,
CollectAlbumTypes,
ParsePlaylistDates,
ParseLargeNumbers,
ParseAlbumTypes,
GenLocales,
GenDict,
DownloadTestfiles,
@ -42,12 +45,16 @@ async fn main() {
Commands::CollectLargeNumbers => {
collect_large_numbers::collect_large_numbers(&cli.project_root, cli.concurrency).await;
}
Commands::CollectAlbumTypes => {
collect_album_types::collect_album_types(&cli.project_root, cli.concurrency).await;
}
Commands::ParsePlaylistDates => {
collect_playlist_dates::write_samples_to_dict(&cli.project_root)
}
Commands::ParseLargeNumbers => {
collect_large_numbers::write_samples_to_dict(&cli.project_root)
}
Commands::ParseAlbumTypes => collect_album_types::write_samples_to_dict(&cli.project_root),
Commands::GenLocales => {
gen_locales::generate_locales(&cli.project_root).await;
}

View file

@ -1,6 +1,6 @@
use std::{collections::BTreeMap, fs::File, io::BufReader, path::Path, str::FromStr};
use rustypipe::param::Language;
use rustypipe::{model::AlbumType, param::Language};
use serde::{Deserialize, Serialize};
const DICT_PATH: &str = "testfiles/dict/dictionary.json";
@ -44,12 +44,21 @@ pub struct DictEntry {
///
/// Format: Parsed token -> decimal power
pub number_tokens: BTreeMap<String, u8>,
/// Names of album types (Album, Single, ...)
///
/// Format: Parsed text -> Album type
pub album_types: BTreeMap<String, AlbumType>,
}
#[derive(Clone, Debug, Deserialize)]
pub struct TextRuns {
pub runs: Vec<Text>,
}
#[derive(Clone, Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Text {
pub simple_text: String,
#[serde(alias = "simpleText")]
pub text: String,
}
pub fn read_dict(project_root: &Path) -> Dictionary {

View file

@ -68,5 +68,5 @@ Dec PL1J-6JOckZtHo91uApeb10Qlf2XhkfM-9 24.12.2021
Album: MPREb_nlBWQROfvjo
Single: MPREb_bHfHGoy7vuv
EP: MPREb_u1I69lSAe5v
Show: MPREb_cwzk8EUwypZ
Audiobook: MPREb_gaoNzsQHedo
Show: MPREb_cwzk8EUwypZ

View file

@ -201,7 +201,7 @@ impl MapResponse<MusicAlbum> for response::MusicPlaylist {
.unwrap_or_default();
let by_va = artists_txt == util::VARIOUS_ARTISTS;
let album_type = map_album_type(album_type_txt.as_str());
let album_type = map_album_type(album_type_txt.as_str(), lang);
let year = year_txt.and_then(|txt| util::parse_numeric(&txt).ok());
let mut mapper = match by_va {

View file

@ -11,7 +11,7 @@ use crate::{
text::{Text, TextComponents},
MapResult, VecLogError,
},
util::{self, TryRemove},
util::{self, dictionary, TryRemove},
};
use super::{
@ -278,7 +278,7 @@ impl MusicListMapper {
}
PageType::Album => {
let album_type = subtitle_p1
.map(|st| map_album_type(st.first_str()))
.map(|st| map_album_type(st.first_str(), self.lang))
.unwrap_or_default();
let (artists, artists_txt) = map_artists(subtitle_p2);
@ -469,12 +469,12 @@ impl MusicListMapper {
true,
) => {
year = util::parse_numeric(year_txt.first_str()).ok();
album_type = map_album_type(atype_txt.first_str());
album_type = map_album_type(atype_txt.first_str(), self.lang);
(artists.clone(), artists_txt.clone())
}
// "Album", <"Oonagh"> (Album variants, new releases)
(Some(atype_txt), Some(p2), _, false) => {
album_type = map_album_type(atype_txt.first_str());
album_type = map_album_type(atype_txt.first_str(), self.lang);
map_artists(Some(p2))
}
_ => {
@ -612,11 +612,10 @@ pub(crate) fn map_artists(artists_p: Option<TextComponents>) -> (Vec<ChannelId>,
(artists, artists_txt)
}
pub(crate) fn map_album_type(txt: &str) -> AlbumType {
// TODO: add support for different languages
match txt {
"Single" => AlbumType::Single,
"EP" => AlbumType::Ep,
_ => AlbumType::Album,
}
pub(crate) fn map_album_type(txt: &str, lang: Language) -> AlbumType {
dictionary::entry(lang)
.album_types
.get(&txt.to_lowercase())
.copied()
.unwrap_or_default()
}

View file

@ -598,7 +598,9 @@ pub struct ChannelTag {
*/
/// Verification status of a channel
#[derive(Default, Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
#[derive(
Default, Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash,
)]
#[non_exhaustive]
pub enum Verification {
#[default]
@ -954,7 +956,9 @@ pub struct MusicPlaylistItem {
}
/// YouTube Music album type
#[derive(Default, Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[derive(
Default, Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash,
)]
#[non_exhaustive]
pub enum AlbumType {
/// Regular album (default)
@ -964,6 +968,10 @@ pub enum AlbumType {
Ep,
/// Single
Single,
/// Audiobook
Audiobook,
/// Show (audio drama)
Show,
}
/// Album identifier
@ -1059,7 +1067,7 @@ pub enum MusicItem {
Playlist(MusicPlaylistItem),
}
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum MusicEntityType {
Track,
Album,

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,583 @@
{
"af": {
"Album": "Album",
"Ep": "EP",
"Single": "Enkelsnit",
"Audiobook": "Oudioboek",
"Show": "Drama"
},
"am": {
"Album": "አልበም",
"Ep": "የተራዘመ አልበም",
"Single": "ነጠላ",
"Audiobook": "ኦዲዮ መጽሐፍ",
"Show": "ትዕይንት"
},
"ar": {
"Album": "ألبوم",
"Ep": "ألبوم قصير",
"Single": "أغنية منفردة",
"Audiobook": "الكتب المسموعة",
"Show": "عرض"
},
"as": {
"Album": "এলবাম",
"Ep": "EP",
"Single": "একক",
"Audiobook": "অডিঅ’বুক",
"Show": "শ্ব’"
},
"az": {
"Album": "Albom",
"Ep": "EP",
"Single": "Tək",
"Audiobook": "Audio kitab",
"Show": "Şou"
},
"be": {
"Album": "Альбом",
"Ep": "Міні-альбом",
"Single": "Сінгл",
"Audiobook": "Аўдыякніга",
"Show": "Шоу"
},
"bg": {
"Album": "Албум",
"Ep": "Миниалбум",
"Single": "Сингъл",
"Audiobook": "Аудиокнига",
"Show": "Предаване"
},
"bn": {
"Album": "অ্যালবাম",
"Ep": "ইপি",
"Single": "সিঙ্গেল",
"Audiobook": "অডিওবুক",
"Show": "শো"
},
"bs": {
"Album": "Album",
"Ep": "EP",
"Single": "Singl",
"Audiobook": "Audio knjiga",
"Show": "Serija"
},
"ca": {
"Album": "Àlbum",
"Ep": "EP",
"Single": "Single",
"Audiobook": "Audiollibre",
"Show": "Programa"
},
"cs": {
"Album": "Album",
"Ep": "EP",
"Single": "Singl",
"Audiobook": "Audiokniha",
"Show": "Zobrazit"
},
"da": {
"Album": "Album",
"Ep": "EP",
"Single": "Single",
"Audiobook": "Lydbog",
"Show": "Lyddrama"
},
"de": {
"Album": "Album",
"Ep": "EP",
"Single": "Single",
"Audiobook": "Hörbuch",
"Show": "Hörspiel"
},
"el": {
"Album": "Άλμπουμ",
"Ep": "EP",
"Single": "Single",
"Audiobook": "Ηχητικό βιβλίο",
"Show": "Εκπομπή"
},
"en": {
"Album": "Album",
"Ep": "EP",
"Single": "Single",
"Audiobook": "Audiobook",
"Show": "Show"
},
"en-GB": {
"Album": "Album",
"Ep": "EP",
"Single": "Single",
"Audiobook": "Audiobook",
"Show": "Show"
},
"en-IN": {
"Album": "Album",
"Ep": "EP",
"Single": "Single",
"Audiobook": "Audiobook",
"Show": "Show"
},
"es": {
"Album": "Álbum",
"Ep": "EP",
"Single": "Single",
"Audiobook": "Audiolibro",
"Show": "Audiodrama"
},
"es-419": {
"Album": "Álbum",
"Ep": "EP",
"Single": "Sencillo",
"Audiobook": "Audiolibro",
"Show": "Programa"
},
"es-US": {
"Album": "Álbum",
"Ep": "EP",
"Single": "Sencillo",
"Audiobook": "Audiolibro",
"Show": "Programa"
},
"et": {
"Album": "Album",
"Ep": "EP",
"Single": "Singel",
"Audiobook": "Audioraamat",
"Show": "Sari"
},
"eu": {
"Album": "Albuma",
"Ep": "EP",
"Single": "Singlea",
"Audiobook": "Audio-liburua",
"Show": "Saioa"
},
"fa": {
"Album": "آلبوم",
"Ep": "پخش فوق‌العاده",
"Single": "تک آهنگ",
"Audiobook": "کتاب صوتی",
"Show": "نمایش"
},
"fi": {
"Album": "Albumi",
"Ep": "EP",
"Single": "Single",
"Audiobook": "Äänikirja",
"Show": "Näytä"
},
"fil": {
"Album": "Album",
"Ep": "EP",
"Single": "Single",
"Audiobook": "Audiobook",
"Show": "Palabas"
},
"fr": {
"Album": "Album",
"Ep": "EP",
"Single": "Single",
"Audiobook": "Livre audio",
"Show": "Émission"
},
"fr-CA": {
"Album": "Album",
"Ep": "Microalbum",
"Single": "Simple",
"Audiobook": "Livre audio",
"Show": "Émission"
},
"gl": {
"Album": "Álbum",
"Ep": "EP",
"Single": "Single",
"Audiobook": "Audiolibro",
"Show": "Programa"
},
"gu": {
"Album": "આલ્બમ",
"Ep": "EP",
"Single": "સિંગલ",
"Audiobook": "ઑડિયોબુક",
"Show": "શો"
},
"hi": {
"Album": "एल्‍बम",
"Ep": "ईपी",
"Single": "सिंगल",
"Audiobook": "ऑडियो बुक",
"Show": "शो"
},
"hr": {
"Album": "Album",
"Ep": "EP",
"Single": "Singl",
"Audiobook": "Audioknjiga",
"Show": "Serija"
},
"hu": {
"Album": "Album",
"Ep": "EP",
"Single": "Kislemez",
"Audiobook": "Hangoskönyv",
"Show": "Műsor"
},
"hy": {
"Album": "Ալբոմ",
"Ep": "EP",
"Single": "Սինգլ",
"Audiobook": "Աուդիոգիրք",
"Show": "Աուդիոդրամա"
},
"id": {
"Album": "Album",
"Ep": "EP",
"Single": "Single",
"Audiobook": "Buku audio",
"Show": "Acara"
},
"is": {
"Album": "Plata",
"Ep": "EP",
"Single": "Smáskífa",
"Audiobook": "Hljóðbók",
"Show": "Þáttur"
},
"it": {
"Album": "Album",
"Ep": "EP",
"Single": "Singolo",
"Audiobook": "Audiolibro",
"Show": "Programma"
},
"iw": {
"Album": "אלבום",
"Ep": "מיני-אלבום",
"Single": "סינגל",
"Audiobook": "ספר אודיו",
"Show": "תסכית"
},
"ja": {
"Album": "アルバム",
"Ep": "EP",
"Single": "シングル",
"Audiobook": "オーディオブック",
"Show": "表示"
},
"ka": {
"Album": "ალბომი",
"Ep": "მინი-ალბომი",
"Single": "სინგლი",
"Audiobook": "აუდიოწიგნი",
"Show": "ჩვენება"
},
"kk": {
"Album": "Альбом",
"Ep": "EP",
"Single": "Сингл",
"Audiobook": "Аудиокітап",
"Show": "Шоу"
},
"km": {
"Album": "អាល់ប៊ុម",
"Ep": "EP",
"Single": "ចម្រៀងទោល",
"Audiobook": "សៀវភៅ​ជា​សំឡេង",
"Show": "កម្មវិធីទូរទស្សន៍"
},
"kn": {
"Album": "ಆಲ್ಬಮ್",
"Ep": "EP",
"Single": "ಒಂದೇ",
"Audiobook": "ಆಡಿಯೋಬುಕ್",
"Show": "ಶೋ"
},
"ko": {
"Album": "앨범",
"Ep": "EP",
"Single": "싱글",
"Audiobook": "오디오북",
"Show": "표시"
},
"ky": {
"Album": "Альбом",
"Ep": "Чакан альбом",
"Single": "Сингл",
"Audiobook": "Аудиокитеп",
"Show": "Шоу"
},
"lo": {
"Album": "ອະລະບໍ້າ",
"Ep": "EP",
"Single": "ຊິງເກິນ",
"Audiobook": "ປຶ້ມສຽງ",
"Show": "ສະແດງ"
},
"lt": {
"Album": "Albumas",
"Ep": "Mini albumas",
"Single": "Singlas",
"Audiobook": "Garsinė knyga",
"Show": "Serialas"
},
"lv": {
"Album": "Albums",
"Ep": "EP ieraksts",
"Single": "Singls",
"Audiobook": "Audiogrāmata",
"Show": "Pārraide"
},
"mk": {
"Album": "Албум",
"Ep": "EP",
"Single": "Сингл",
"Audiobook": "Аудиокнига",
"Show": "Серија"
},
"ml": {
"Album": "ആല്‍‌ബം",
"Ep": "EP",
"Single": "സിംഗിൾ",
"Audiobook": "ഓഡിയോ ബുക്ക്",
"Show": "ഷോ"
},
"mn": {
"Album": "Цомог",
"Ep": "EP",
"Single": "Сингл",
"Audiobook": "Аудио ном",
"Show": "Жүжиг"
},
"mr": {
"Album": "अल्बम",
"Ep": "भाग",
"Single": "सिंगल",
"Audiobook": "ऑडिओबुक",
"Show": "शो"
},
"ms": {
"Album": "Album",
"Ep": "EP",
"Single": "Rekod single",
"Audiobook": "Buku audio",
"Show": "Rancangan"
},
"my": {
"Album": "အယ်လ်ဘမ်",
"Ep": "EP",
"Single": "တစ်ကိုယ်တော်",
"Audiobook": "အော်ဒီယိုစာအုပ်",
"Show": "ရှိုး"
},
"ne": {
"Album": "एल्बम",
"Ep": "EP",
"Single": "एकल एल्बम",
"Audiobook": "अडियोबुक",
"Show": "टिभी सो"
},
"nl": {
"Album": "Album",
"Ep": "Ep",
"Single": "Single",
"Audiobook": "Audioboek",
"Show": "Aflevering"
},
"no": {
"Album": "Album",
"Ep": "EP",
"Single": "Singel",
"Audiobook": "Lydbok",
"Show": "Hørespill"
},
"or": {
"Album": "ଆଲବମ୍",
"Ep": "EP",
"Single": "ସିଙ୍ଗଲ୍",
"Audiobook": "ଅଡିଓବୁକ୍",
"Show": "ଶୋ"
},
"pa": {
"Album": "ਐਲਬਮ",
"Ep": "EP",
"Single": "ਸਿੰਗਲ",
"Audiobook": "ਆਡੀਓ-ਕਿਤਾਬ",
"Show": "ਸ਼ੋਅ"
},
"pl": {
"Album": "Album",
"Ep": "EP",
"Single": "Singiel",
"Audiobook": "Audiobook",
"Show": "Słuchowisko"
},
"pt": {
"Album": "Álbum",
"Ep": "EP",
"Single": "Single",
"Audiobook": "Audiolivro",
"Show": "Programa"
},
"pt-PT": {
"Album": "Álbum",
"Ep": "EP",
"Single": "Single",
"Audiobook": "Livro áudio",
"Show": "Programa"
},
"ro": {
"Album": "Album",
"Ep": "EP",
"Single": "Single",
"Audiobook": "Carte audio",
"Show": "Emisiune"
},
"ru": {
"Album": "Альбом",
"Ep": "EP",
"Single": "Сингл",
"Audiobook": "Аудиокнига",
"Show": "Аудиошоу"
},
"si": {
"Album": "ඇල්බමය",
"Ep": "දීවා",
"Single": "තනි",
"Audiobook": "ශ්‍රව්‍යපොත",
"Show": "සංදර්ශනය"
},
"sk": {
"Album": "Album",
"Ep": "EP",
"Single": "Singel",
"Audiobook": "Audiokniha",
"Show": "Relácia"
},
"sl": {
"Album": "Album",
"Ep": "EP",
"Single": "Singel",
"Audiobook": "Zvočna knjiga",
"Show": "Oddaja"
},
"sq": {
"Album": "Album",
"Ep": "EP",
"Single": "Single",
"Audiobook": "Libër me audio",
"Show": "Shfaq"
},
"sr": {
"Album": "Албум",
"Ep": "EP",
"Single": "Сингл",
"Audiobook": "Аудио-књига",
"Show": "Серија"
},
"sr-Latn": {
"Album": "Album",
"Ep": "EP",
"Single": "Singl",
"Audiobook": "Audio-knjiga",
"Show": "Serija"
},
"sv": {
"Album": "Album",
"Ep": "EP",
"Single": "Singel",
"Audiobook": "Ljudbok",
"Show": "Ljuddrama"
},
"sw": {
"Album": "Albamu",
"Ep": "EP",
"Single": "Singo",
"Audiobook": "Kitabu cha kusikiliza",
"Show": "Kipindi"
},
"ta": {
"Album": "ஆல்பம்",
"Ep": "EP",
"Single": "சிங்கிள்",
"Audiobook": "ஆடியோ புத்தகம்",
"Show": "ஆடியோ ஷோ"
},
"te": {
"Album": "ఆల్బమ్",
"Ep": "EP",
"Single": "సింగిల్",
"Audiobook": "ఆడియోబుక్",
"Show": "చూపించు"
},
"th": {
"Album": "อัลบั้ม",
"Ep": "EP",
"Single": "ซิงเกิล",
"Audiobook": "หนังสือเสียง",
"Show": "รายการ"
},
"tr": {
"Album": "Albüm",
"Ep": "EP",
"Single": "Single",
"Audiobook": "Sesli kitap",
"Show": "Program"
},
"uk": {
"Album": "Альбом",
"Ep": "Мініальбом",
"Single": "Сингл",
"Audiobook": "Аудіокнига",
"Show": "Аудіодрама"
},
"ur": {
"Album": "البم",
"Ep": "EP",
"Single": "واحد",
"Audiobook": "آڈیو بک",
"Show": "شو"
},
"uz": {
"Album": "Albom",
"Ep": "EP",
"Single": "Singl",
"Audiobook": "Audiokitob",
"Show": "Shou"
},
"vi": {
"Album": "Đĩa nhạc",
"Ep": "Đĩa nhạc mở rộng (EP)",
"Single": "Đĩa đơn",
"Audiobook": "Sách nói",
"Show": "Chương trình"
},
"zh-CN": {
"Album": "专辑",
"Ep": "迷你专辑",
"Single": "单曲",
"Audiobook": "有声读物",
"Show": "广播剧"
},
"zh-HK": {
"Album": "專輯",
"Ep": "EP",
"Single": "單曲",
"Audiobook": "有聲書",
"Show": "節目"
},
"zh-TW": {
"Album": "專輯",
"Ep": "EP",
"Single": "單曲",
"Audiobook": "有聲書",
"Show": "節目"
},
"zu": {
"Album": "I-albhamu",
"Ep": "I-EP",
"Single": "I-Single",
"Audiobook": "I-audiobook",
"Show": "Bonisa"
}
}

File diff suppressed because it is too large Load diff

View file

@ -9,7 +9,7 @@ MusicAlbum(
cover: "[cover]",
artists: [],
artists_txt: "George Orwell & Dirk Jacobs",
album_type: Album,
album_type: Audiobook,
year: Some(2022),
by_va: false,
tracks: [

View file

@ -14,7 +14,7 @@ MusicAlbum(
),
],
artists_txt: "Kingdom Force",
album_type: Album,
album_type: Show,
year: Some(2022),
by_va: false,
tracks: [