feat: multilanguage album type parsing
- new album types: Audiobook, Show
This commit is contained in:
parent
abfd630a04
commit
45e2d3c7c7
15 changed files with 2354 additions and 32 deletions
121
codegen/src/collect_album_types.rs
Normal file
121
codegen/src/collect_album_types.rs
Normal 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
|
||||
}
|
||||
|
|
@ -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(),
|
||||
)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
583
testfiles/dict/album_type_samples.json
Normal file
583
testfiles/dict/album_type_samples.json
Normal 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
|
|
@ -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: [
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ MusicAlbum(
|
|||
),
|
||||
],
|
||||
artists_txt: "Kingdom Force",
|
||||
album_type: Album,
|
||||
album_type: Show,
|
||||
year: Some(2022),
|
||||
by_va: false,
|
||||
tracks: [
|
||||
|
|
|
|||
Reference in a new issue