mirror of
https://github.com/SinTan1729/movie-rename.git
synced 2025-04-20 02:40:00 -05:00
Compare commits
No commits in common. "main" and "2.1.3" have entirely different histories.
10 changed files with 528 additions and 1345 deletions
1566
Cargo.lock
generated
1566
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
14
Cargo.toml
14
Cargo.toml
|
@ -1,7 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "movie-rename"
|
name = "movie-rename"
|
||||||
version = "2.3.2"
|
version = "2.1.3"
|
||||||
build = "build.rs"
|
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["Sayantan Santra <sayantan[dot]santra689[at]gmail[dot]com"]
|
authors = ["Sayantan Santra <sayantan[dot]santra689[at]gmail[dot]com"]
|
||||||
license = "GPL-3.0"
|
license = "GPL-3.0"
|
||||||
|
@ -17,15 +16,10 @@ categories = ["command-line-utilities"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
torrent-name-parser = "0.12.1"
|
torrent-name-parser = "0.12.1"
|
||||||
tmdb-api = "0.8.0"
|
tmdb-api = "0.4.0"
|
||||||
inquire = "0.7.5"
|
inquire = "0.6.2"
|
||||||
load_file = "1.0.1"
|
load_file = "1.0.1"
|
||||||
tokio = { version = "1.32.0", features = ["macros", "rt-multi-thread"] }
|
tokio = { version = "1.28.1", features = ["macros", "rt-multi-thread"] }
|
||||||
clap = { version = "4.5.1", features = ["cargo"] }
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
clap = { version = "4.5.1", features = ["cargo"] }
|
|
||||||
clap_complete = "4.5.1"
|
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
strip = true
|
strip = true
|
||||||
|
|
4
Makefile
4
Makefile
|
@ -2,7 +2,7 @@ PREFIX := /usr/local
|
||||||
PKGNAME := movie-rename
|
PKGNAME := movie-rename
|
||||||
|
|
||||||
build:
|
build:
|
||||||
cargo zigbuild --release --target x86_64-unknown-linux-gnu.2.34
|
cargo build --release
|
||||||
|
|
||||||
build-debug:
|
build-debug:
|
||||||
cargo build
|
cargo build
|
||||||
|
@ -19,6 +19,6 @@ uninstall:
|
||||||
rm -f "$(DESTDIR)$(PREFIX)/man/man1/$(PKGNAME).1"
|
rm -f "$(DESTDIR)$(PREFIX)/man/man1/$(PKGNAME).1"
|
||||||
|
|
||||||
aur: build
|
aur: build
|
||||||
tar --transform 's/.*\///g' -czf $(PKGNAME).tar.gz target/x86_64-unknown-linux-gnu/release/$(PKGNAME) target/autocomplete/* $(PKGNAME).1
|
tar --transform 's/.*\///g' -czf $(PKGNAME).tar.gz target/release/$(PKGNAME) $(PKGNAME).1
|
||||||
|
|
||||||
.PHONY: build build-debug install clean uninstall aur
|
.PHONY: build build-debug install clean uninstall aur
|
||||||
|
|
|
@ -30,8 +30,7 @@ sudo make install
|
||||||
- Default pattern is `{title} ({year}) - {director}`. Extension is always kept.
|
- Default pattern is `{title} ({year}) - {director}`. Extension is always kept.
|
||||||
- Passing `--directory` or `-d` assumes that the arguments are directory names, which contain exactly one movie and optionally subtitles.
|
- Passing `--directory` or `-d` assumes that the arguments are directory names, which contain exactly one movie and optionally subtitles.
|
||||||
- Passing `--dry-run` or `-n` does a dry tun and only prints out the new names, without actually doing anything.
|
- Passing `--dry-run` or `-n` does a dry tun and only prints out the new names, without actually doing anything.
|
||||||
- Passing `--i-feel-lucky` or `-l` automatically chooses the first option. Useful when you use the program as part of a script.
|
- Passing `-nd` or `-dn` does a dry run in directory mode.
|
||||||
- You can join the short flags `-d`, `-n` and `-l` together (e.g. `-dn` or `-dln`).
|
|
||||||
- Passing `--help` or `-h` shows help and exits.
|
- Passing `--help` or `-h` shows help and exits.
|
||||||
- Passing `--version` or `-v` shows version and exits.
|
- Passing `--version` or `-v` shows version and exits.
|
||||||
|
|
||||||
|
|
21
build.rs
21
build.rs
|
@ -1,21 +0,0 @@
|
||||||
use clap_complete::generate_to;
|
|
||||||
use clap_complete::shells::{Bash, Fish, Zsh};
|
|
||||||
use std::env;
|
|
||||||
use std::ffi::OsString;
|
|
||||||
use std::fs::{create_dir, remove_dir_all};
|
|
||||||
use std::io::Error;
|
|
||||||
|
|
||||||
include!("src/args.rs");
|
|
||||||
|
|
||||||
fn main() -> Result<(), Error> {
|
|
||||||
let target = "./target/autocomplete";
|
|
||||||
remove_dir_all(target).ok();
|
|
||||||
create_dir(target)?;
|
|
||||||
let outdir = OsString::from(target);
|
|
||||||
|
|
||||||
let mut cmd = get_command();
|
|
||||||
generate_to(Bash, &mut cmd, "movie-rename", &outdir)?;
|
|
||||||
generate_to(Fish, &mut cmd, "movie-rename", &outdir)?;
|
|
||||||
generate_to(Zsh, &mut cmd, "movie-rename", &outdir)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
|
@ -17,6 +17,9 @@ Performs a dry run, without actually renaming anything.
|
||||||
-d, --directory
|
-d, --directory
|
||||||
Runs in directory mode. In this mode, it is assumed that the arguments are directory names, which contain exactly one movie and optionally subtitles.
|
Runs in directory mode. In this mode, it is assumed that the arguments are directory names, which contain exactly one movie and optionally subtitles.
|
||||||
.TP
|
.TP
|
||||||
|
-dn, -nd
|
||||||
|
Performs a dry run in directory mode.
|
||||||
|
.TP
|
||||||
-h, --help
|
-h, --help
|
||||||
Print help information.
|
Print help information.
|
||||||
.TP
|
.TP
|
||||||
|
|
46
src/args.rs
46
src/args.rs
|
@ -1,46 +0,0 @@
|
||||||
use clap::{arg, command, ArgAction, Command, ValueHint};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
// Bare command generation function to help with autocompletion
|
|
||||||
pub fn get_command() -> Command {
|
|
||||||
command!()
|
|
||||||
.name("movie-rename")
|
|
||||||
.author("Sayantan Santra <sayantan.santra@gmail.com>")
|
|
||||||
.about("A simple tool to rename movies, written in Rust.")
|
|
||||||
.arg(arg!(-d --directory "Run in directory mode").action(ArgAction::SetTrue))
|
|
||||||
.arg(arg!(-n --"dry-run" "Do a dry run").action(ArgAction::SetTrue))
|
|
||||||
.arg(arg!(-l --"i-feel-lucky" "Always choose the first option").action(ArgAction::SetTrue))
|
|
||||||
.arg(
|
|
||||||
arg!([entries] "The files/directories to be processed")
|
|
||||||
.trailing_var_arg(true)
|
|
||||||
.num_args(1..)
|
|
||||||
.value_hint(ValueHint::AnyPath)
|
|
||||||
.required(true),
|
|
||||||
)
|
|
||||||
// Use -v instead of -V for version
|
|
||||||
.disable_version_flag(true)
|
|
||||||
.arg(arg!(-v --version "Print version").action(ArgAction::Version))
|
|
||||||
.arg_required_else_help(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function to process the passed arguments
|
|
||||||
pub fn process_args() -> (Vec<String>, HashMap<String, bool>) {
|
|
||||||
let matches = get_command().get_matches();
|
|
||||||
|
|
||||||
// Generate the settings HashMap from read flags
|
|
||||||
let mut settings = HashMap::new();
|
|
||||||
for id in matches.ids().map(|x| x.as_str()) {
|
|
||||||
if id != "entries" {
|
|
||||||
settings.insert(id.to_string(), matches.get_flag(id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Every unmatched argument should be treated as a file entry
|
|
||||||
let entries: Vec<String> = matches
|
|
||||||
.get_many::<String>("entries")
|
|
||||||
.expect("No entries provided!")
|
|
||||||
.cloned()
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
(entries, settings)
|
|
||||||
}
|
|
111
src/functions.rs
111
src/functions.rs
|
@ -2,23 +2,25 @@ use inquire::{
|
||||||
ui::{Color, IndexPrefix, RenderConfig, Styled},
|
ui::{Color, IndexPrefix, RenderConfig, Styled},
|
||||||
InquireError, Select,
|
InquireError, Select,
|
||||||
};
|
};
|
||||||
use std::{collections::HashMap, fs, path::Path};
|
use std::{collections::HashMap, fs, path::Path, process::exit};
|
||||||
use tmdb_api::{
|
use tmdb_api::{
|
||||||
client::{reqwest::ReqwestExecutor, Client},
|
|
||||||
movie::{credits::MovieCredits, search::MovieSearch},
|
movie::{credits::MovieCredits, search::MovieSearch},
|
||||||
prelude::Command,
|
prelude::Command,
|
||||||
|
Client,
|
||||||
};
|
};
|
||||||
use torrent_name_parser::Metadata;
|
use torrent_name_parser::Metadata;
|
||||||
|
|
||||||
use crate::structs::{get_long_lang, Language, MovieEntry};
|
use crate::structs::{get_long_lang, Language, MovieEntry};
|
||||||
|
|
||||||
|
// Get the version from Cargo.toml
|
||||||
|
const VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
||||||
// Function to process movie entries
|
// Function to process movie entries
|
||||||
pub async fn process_file(
|
pub async fn process_file(
|
||||||
filename: &String,
|
filename: &String,
|
||||||
tmdb: &Client<ReqwestExecutor>,
|
tmdb: &Client,
|
||||||
pattern: &str,
|
pattern: &str,
|
||||||
dry_run: bool,
|
dry_run: bool,
|
||||||
lucky: bool,
|
|
||||||
movie_list: Option<&HashMap<String, Option<String>>>,
|
movie_list: Option<&HashMap<String, Option<String>>>,
|
||||||
// The last bool tells whether the entry should be added to the movie_list or not
|
// The last bool tells whether the entry should be added to the movie_list or not
|
||||||
// The first String is filename without extension, and the second String is
|
// The first String is filename without extension, and the second String is
|
||||||
|
@ -127,28 +129,22 @@ pub async fn process_file(
|
||||||
return (filename_without_ext, None, true);
|
return (filename_without_ext, None, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
let choice;
|
// Choose from the possible entries
|
||||||
if lucky {
|
let choice = match Select::new(
|
||||||
// Take first choice if in lucky mode
|
format!(" Possible choices for {file_base}:").as_str(),
|
||||||
choice = movie_list.into_iter().next().unwrap();
|
movie_list,
|
||||||
} else {
|
)
|
||||||
// Choose from the possible entries
|
.prompt()
|
||||||
choice = match Select::new(
|
{
|
||||||
format!(" Possible choices for {file_base}:").as_str(),
|
Ok(movie) => movie,
|
||||||
movie_list,
|
Err(error) => {
|
||||||
)
|
println!(" {error}");
|
||||||
.prompt()
|
let flag = matches!(
|
||||||
{
|
error,
|
||||||
Ok(movie) => movie,
|
InquireError::OperationCanceled | InquireError::OperationInterrupted
|
||||||
Err(error) => {
|
);
|
||||||
println!(" {error}");
|
return (filename_without_ext, None, flag);
|
||||||
let flag = matches!(
|
}
|
||||||
error,
|
|
||||||
InquireError::OperationCanceled | InquireError::OperationInterrupted
|
|
||||||
);
|
|
||||||
return (filename_without_ext, None, flag);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create the new name
|
// Create the new name
|
||||||
|
@ -205,8 +201,69 @@ pub async fn process_file(
|
||||||
(filename_without_ext, Some(new_name_base), true)
|
(filename_without_ext, Some(new_name_base), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to process the passed arguments
|
||||||
|
pub fn process_args(mut args: Vec<String>) -> (Vec<String>, HashMap<&'static str, bool>) {
|
||||||
|
// Remove the entry corresponding to the running process
|
||||||
|
args.remove(0);
|
||||||
|
let mut entries = Vec::new();
|
||||||
|
let mut settings = HashMap::from([("dry_run", false), ("directory", false)]);
|
||||||
|
for arg in args {
|
||||||
|
match arg.as_str() {
|
||||||
|
"--help" | "-h" => {
|
||||||
|
println!(" The expected syntax is:");
|
||||||
|
println!(
|
||||||
|
" movie-rename <filename(s)> [-n|--dry-run] [-d|--directory] [-v|--version]"
|
||||||
|
);
|
||||||
|
println!(
|
||||||
|
" There needs to be a config file named config in the $XDG_CONFIG_HOME/movie-rename/ directory."
|
||||||
|
);
|
||||||
|
println!(" It should consist of two lines. The first line should have your TMDb API key.");
|
||||||
|
println!(
|
||||||
|
" The second line should have a pattern, that will be used for the rename."
|
||||||
|
);
|
||||||
|
println!(" In the pattern, the variables need to be enclosed in {{}}, the supported variables are `title`, `year` and `director`.");
|
||||||
|
println!(
|
||||||
|
" Default pattern is `{{title}} ({{year}}) - {{director}}`. Extension is always kept."
|
||||||
|
);
|
||||||
|
println!(" Passing --directory or -d assumes that the arguments are directory names, which contain exactly one movie and optionally subtitles.");
|
||||||
|
println!(" Passing --dry-run or -n does a dry tun and only prints out the new names, without actually doing anything.");
|
||||||
|
println!(" Passing -nd or -dn does a dry run in directory mode.");
|
||||||
|
println!(" Passing --version or -v shows version and exits.");
|
||||||
|
println!(" Pass --help to get this again.");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
"--version" | "-v" => {
|
||||||
|
println!("movie-rename {VERSION}");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
"--dry-run" | "-n" => {
|
||||||
|
println!("Doing a dry run...");
|
||||||
|
settings.entry("dry_run").and_modify(|x| *x = true);
|
||||||
|
}
|
||||||
|
"--directory" | "-d" => {
|
||||||
|
println!("Running in directory mode...");
|
||||||
|
settings.entry("directory").and_modify(|x| *x = true);
|
||||||
|
}
|
||||||
|
"-nd" | "-dn" => {
|
||||||
|
println!("Doing a dry run in directory mode...");
|
||||||
|
settings.entry("dry_run").and_modify(|x| *x = true);
|
||||||
|
settings.entry("directory").and_modify(|x| *x = true);
|
||||||
|
}
|
||||||
|
other => {
|
||||||
|
if other.starts_with('-') {
|
||||||
|
eprintln!("Unknown argument passed: {other}");
|
||||||
|
exit(1);
|
||||||
|
} else {
|
||||||
|
entries.push(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(entries, settings)
|
||||||
|
}
|
||||||
|
|
||||||
// RenderConfig for the menu items
|
// RenderConfig for the menu items
|
||||||
fn get_render_config() -> RenderConfig<'static> {
|
fn get_render_config() -> RenderConfig {
|
||||||
let mut render_config = RenderConfig::default();
|
let mut render_config = RenderConfig::default();
|
||||||
render_config.option_index_prefix = IndexPrefix::Simple;
|
render_config.option_index_prefix = IndexPrefix::Simple;
|
||||||
|
|
||||||
|
|
35
src/main.rs
35
src/main.rs
|
@ -1,31 +1,19 @@
|
||||||
use load_file::{self, load_str};
|
use load_file::{self, load_str};
|
||||||
use std::{collections::HashMap, env, fs, path::Path, process::exit};
|
use std::{collections::HashMap, env, fs, path::Path, process::exit};
|
||||||
use tmdb_api::client::{reqwest::ReqwestExecutor, Client};
|
use tmdb_api::Client;
|
||||||
|
|
||||||
// Import all the modules
|
// Import all the modules
|
||||||
mod functions;
|
mod functions;
|
||||||
use functions::process_file;
|
use functions::{process_args, process_file};
|
||||||
mod args;
|
|
||||||
mod structs;
|
mod structs;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
// Process the passed arguments
|
// Read arguments from commandline
|
||||||
let (entries, settings) = args::process_args();
|
let args: Vec<String> = env::args().collect();
|
||||||
let flag_dry_run = settings["dry-run"];
|
|
||||||
let flag_directory = settings["directory"];
|
|
||||||
let flag_lucky = settings["i-feel-lucky"];
|
|
||||||
|
|
||||||
// Print some message when flags are set.
|
// Process the passed arguments
|
||||||
if flag_dry_run {
|
let (entries, settings) = process_args(args);
|
||||||
println!("Doing a dry run. No files will be modified.")
|
|
||||||
}
|
|
||||||
if flag_directory {
|
|
||||||
println!("Running in directory mode...")
|
|
||||||
}
|
|
||||||
if flag_lucky {
|
|
||||||
println!("Automatically selecting the first entry...")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to read config file, or display error
|
// Try to read config file, or display error
|
||||||
let mut config_file = env::var("XDG_CONFIG_HOME").unwrap_or(String::from("$HOME"));
|
let mut config_file = env::var("XDG_CONFIG_HOME").unwrap_or(String::from("$HOME"));
|
||||||
|
@ -50,17 +38,17 @@ async fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create TMDb object for API calls
|
// Create TMDb object for API calls
|
||||||
let tmdb = Client::<ReqwestExecutor>::new(String::from(api_key));
|
let tmdb = Client::new(String::from(api_key));
|
||||||
|
|
||||||
// Iterate over entries
|
// Iterate over entries
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
// Check if the file/directory exists on disk and run necessary commands
|
// Check if the file/directory exists on disk and run necessary commands
|
||||||
match flag_directory {
|
match settings["directory"] {
|
||||||
// Normal file
|
// Normal file
|
||||||
false => {
|
false => {
|
||||||
if Path::new(entry.as_str()).is_file() {
|
if Path::new(entry.as_str()).is_file() {
|
||||||
// Process the filename for movie entries
|
// Process the filename for movie entries
|
||||||
process_file(&entry, &tmdb, pattern, flag_dry_run, flag_lucky, None).await;
|
process_file(&entry, &tmdb, pattern, settings["dry_run"], None).await;
|
||||||
} else {
|
} else {
|
||||||
eprintln!("The file {entry} wasn't found on disk, skipping...");
|
eprintln!("The file {entry} wasn't found on disk, skipping...");
|
||||||
continue;
|
continue;
|
||||||
|
@ -81,8 +69,7 @@ async fn main() {
|
||||||
&filename,
|
&filename,
|
||||||
&tmdb,
|
&tmdb,
|
||||||
pattern,
|
pattern,
|
||||||
flag_dry_run,
|
settings["dry_run"],
|
||||||
flag_lucky,
|
|
||||||
Some(&movie_list),
|
Some(&movie_list),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
@ -113,7 +100,7 @@ async fn main() {
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
println!("[directory] '{entry_clean}' -> '{name}'",);
|
println!("[directory] '{entry_clean}' -> '{name}'",);
|
||||||
if !flag_dry_run {
|
if !settings["dry_run"] {
|
||||||
if !Path::new(name.as_str()).is_dir() {
|
if !Path::new(name.as_str()).is_dir() {
|
||||||
fs::rename(entry, name)
|
fs::rename(entry, name)
|
||||||
.expect("Unable to rename directory!");
|
.expect("Unable to rename directory!");
|
||||||
|
|
|
@ -65,19 +65,20 @@ impl fmt::Display for MovieEntry {
|
||||||
let mut buffer = String::new();
|
let mut buffer = String::new();
|
||||||
buffer.push_str(&format!("{} ", self.title));
|
buffer.push_str(&format!("{} ", self.title));
|
||||||
|
|
||||||
if let Some(year) = &self.year {
|
if self.year.is_some() {
|
||||||
buffer.push_str(&format!("({year}), "));
|
buffer.push_str(&format!("({}), ", self.year.as_ref().unwrap()));
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.push_str(&format!(
|
buffer.push_str(&format!(
|
||||||
"Language: {}, ",
|
"Language: {}, ",
|
||||||
get_long_lang(self.language.as_str())
|
get_long_lang(self.language.as_str())
|
||||||
));
|
));
|
||||||
|
|
||||||
if let Some(director) = &self.director {
|
if self.director.is_some() {
|
||||||
buffer.push_str(&format!("Directed by: {director}, "));
|
buffer.push_str(&format!(
|
||||||
|
"Directed by: {}, ",
|
||||||
|
self.director.as_ref().unwrap()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.push_str(&format!("TMDB ID: {}", self.id));
|
buffer.push_str(&format!("TMDB ID: {}", self.id));
|
||||||
// buffer.push_str(&format!("Synopsis: {}", self.overview));
|
// buffer.push_str(&format!("Synopsis: {}", self.overview));
|
||||||
write!(f, "{buffer}")
|
write!(f, "{buffer}")
|
||||||
|
@ -112,50 +113,19 @@ impl fmt::Display for Language {
|
||||||
|
|
||||||
// Get long name of a language
|
// Get long name of a language
|
||||||
pub fn get_long_lang(short: &str) -> String {
|
pub fn get_long_lang(short: &str) -> String {
|
||||||
// List used from https://gist.github.com/carlopires/1262033/c52ef0f7ce4f58108619508308372edd8d0bd518#file-gistfile1-txt
|
let long = match short {
|
||||||
#[rustfmt::skip]
|
"en" => "English",
|
||||||
static LANG_LIST: [(&str, &str); 185] = [("ab", "Abkhaz"), ("aa", "Afar"), ("af", "Afrikaans"), ("ak", "Akan"), ("sq", "Albanian"),
|
"hi" => "Hindi",
|
||||||
("am", "Amharic"), ("ar", "Arabic"), ("an", "Aragonese"), ("hy", "Armenian"), ("as", "Assamese"), ("av", "Avaric"),
|
"bn" => "Bengali",
|
||||||
("ae", "Avestan"), ("ay", "Aymara"), ("az", "Azerbaijani"), ("bm", "Bambara"), ("ba", "Bashkir"), ("eu", "Basque"),
|
"fr" => "French",
|
||||||
("be", "Belarusian"), ("bn", "Bengali"), ("bh", "Bihari"), ("bi", "Bislama"), ("bs", "Bosnian"), ("br", "Breton"),
|
"ja" => "Japanese",
|
||||||
("bg", "Bulgarian"), ("my", "Burmese"), ("ca", "Catalan; Valencian"), ("ch", "Chamorro"), ("ce", "Chechen"),
|
"de" => "German",
|
||||||
("ny", "Chichewa; Chewa; Nyanja"), ("zh", "Chinese"), ("cv", "Chuvash"), ("kw", "Cornish"), ("co", "Corsican"),
|
"sp" => "Spanish",
|
||||||
("cr", "Cree"), ("hr", "Croatian"), ("cs", "Czech"), ("da", "Danish"), ("dv", "Divehi; Maldivian;"), ("nl", "Dutch"),
|
"fa" => "Persian",
|
||||||
("dz", "Dzongkha"), ("en", "English"), ("eo", "Esperanto"), ("et", "Estonian"), ("ee", "Ewe"), ("fo", "Faroese"),
|
"none" => "None",
|
||||||
("fj", "Fijian"), ("fi", "Finnish"), ("fr", "French"), ("ff", "Fula"), ("gl", "Galician"), ("ka", "Georgian"),
|
other => other,
|
||||||
("de", "German"), ("el", "Greek, Modern"), ("gn", "Guaraní"), ("gu", "Gujarati"), ("ht", "Haitian"), ("ha", "Hausa"),
|
};
|
||||||
("he", "Hebrew (modern)"), ("hz", "Herero"), ("hi", "Hindi"), ("ho", "Hiri Motu"), ("hu", "Hungarian"), ("ia", "Interlingua"),
|
String::from(long)
|
||||||
("id", "Indonesian"), ("ie", "Interlingue"), ("ga", "Irish"), ("ig", "Igbo"), ("ik", "Inupiaq"), ("io", "Ido"), ("is", "Icelandic"),
|
|
||||||
("it", "Italian"), ("iu", "Inuktitut"), ("ja", "Japanese"), ("jv", "Javanese"), ("kl", "Kalaallisut"), ("kn", "Kannada"),
|
|
||||||
("kr", "Kanuri"), ("ks", "Kashmiri"), ("kk", "Kazakh"), ("km", "Khmer"), ("ki", "Kikuyu, Gikuyu"), ("rw", "Kinyarwanda"),
|
|
||||||
("ky", "Kirghiz, Kyrgyz"), ("kv", "Komi"), ("kg", "Kongo"), ("ko", "Korean"), ("ku", "Kurdish"), ("kj", "Kwanyama, Kuanyama"),
|
|
||||||
("la", "Latin"), ("lb", "Luxembourgish"), ("lg", "Luganda"), ("li", "Limburgish"), ("ln", "Lingala"), ("lo", "Lao"), ("lt", "Lithuanian"),
|
|
||||||
("lu", "Luba-Katanga"), ("lv", "Latvian"), ("gv", "Manx"), ("mk", "Macedonian"), ("mg", "Malagasy"), ("ms", "Malay"), ("ml", "Malayalam"),
|
|
||||||
("mt", "Maltese"), ("mi", "Māori"), ("mr", "Marathi (Marāṭhī)"), ("mh", "Marshallese"), ("mn", "Mongolian"), ("na", "Nauru"),
|
|
||||||
("nv", "Navajo, Navaho"), ("nb", "Norwegian Bokmål"), ("nd", "North Ndebele"), ("ne", "Nepali"), ("ng", "Ndonga"),
|
|
||||||
("nn", "Norwegian Nynorsk"), ("no", "Norwegian"), ("ii", "Nuosu"), ("nr", "South Ndebele"), ("oc", "Occitan"), ("oj", "Ojibwe, Ojibwa"),
|
|
||||||
("cu", "Old Church Slavonic"), ("om", "Oromo"), ("or", "Oriya"), ("os", "Ossetian, Ossetic"), ("pa", "Panjabi, Punjabi"), ("pi", "Pāli"),
|
|
||||||
("fa", "Persian"), ("pl", "Polish"), ("ps", "Pashto, Pushto"), ("pt", "Portuguese"), ("qu", "Quechua"), ("rm", "Romansh"), ("rn", "Kirundi"),
|
|
||||||
("ro", "Romanian, Moldavan"), ("ru", "Russian"), ("sa", "Sanskrit (Saṁskṛta)"), ("sc", "Sardinian"), ("sd", "Sindhi"), ("se", "Northern Sami"),
|
|
||||||
("sm", "Samoan"), ("sg", "Sango"), ("sr", "Serbian"), ("gd", "Scottish Gaelic"), ("sn", "Shona"), ("si", "Sinhala, Sinhalese"), ("sk", "Slovak"),
|
|
||||||
("sl", "Slovene"), ("so", "Somali"), ("st", "Southern Sotho"), ("es", "Spanish; Castilian"), ("su", "Sundanese"), ("sw", "Swahili"),
|
|
||||||
("ss", "Swati"), ("sv", "Swedish"), ("ta", "Tamil"), ("te", "Telugu"), ("tg", "Tajik"), ("th", "Thai"), ("ti", "Tigrinya"), ("bo", "Tibetan"),
|
|
||||||
("tk", "Turkmen"), ("tl", "Tagalog"), ("tn", "Tswana"), ("to", "Tonga"), ("tr", "Turkish"), ("ts", "Tsonga"), ("tt", "Tatar"), ("tw", "Twi"),
|
|
||||||
("ty", "Tahitian"), ("ug", "Uighur, Uyghur"), ("uk", "Ukrainian"), ("ur", "Urdu"), ("uz", "Uzbek"), ("ve", "Venda"), ("vi", "Vietnamese"),
|
|
||||||
("vo", "Volapük"), ("wa", "Walloon"), ("cy", "Welsh"), ("wo", "Wolof"), ("fy", "Western Frisian"), ("xh", "Xhosa"), ("yi", "Yiddish"),
|
|
||||||
("yo", "Yoruba"), ("za", "Zhuang, Chuang"), ("zu", "Zulu"), ("none", "None")];
|
|
||||||
|
|
||||||
let long = LANG_LIST
|
|
||||||
.iter()
|
|
||||||
.filter(|x| x.0 == short)
|
|
||||||
.map(|x| x.1)
|
|
||||||
.next();
|
|
||||||
|
|
||||||
if let Some(longlang) = long {
|
|
||||||
String::from(longlang)
|
|
||||||
} else {
|
|
||||||
String::from(short)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanitize filename so that there are no errors while
|
// Sanitize filename so that there are no errors while
|
||||||
|
|
Loading…
Reference in a new issue