trailers.to subtitles + subtitle helper

This commit is contained in:
LagradOst 2021-08-01 00:11:56 +02:00
parent 938a8e2a18
commit 6b27db036b
5 changed files with 386 additions and 20 deletions

View file

@ -2,6 +2,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" package="com.lagradost.cloudstream3"> xmlns:tools="http://schemas.android.com/tools" package="com.lagradost.cloudstream3">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

View file

@ -31,8 +31,10 @@ import com.lagradost.cloudstream3.utils.DataStore.getKey
import com.lagradost.cloudstream3.utils.DataStore.removeKey import com.lagradost.cloudstream3.utils.DataStore.removeKey
import com.lagradost.cloudstream3.utils.DataStoreHelper.setViewPos import com.lagradost.cloudstream3.utils.DataStoreHelper.setViewPos
import com.lagradost.cloudstream3.utils.Event import com.lagradost.cloudstream3.utils.Event
import com.lagradost.cloudstream3.utils.SubtitleHelper.createISO
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.fragment_result.* import kotlinx.android.synthetic.main.fragment_result.*
import kotlin.concurrent.thread
const val VLC_PACKAGE = "org.videolan.vlc" const val VLC_PACKAGE = "org.videolan.vlc"
const val VLC_INTENT_ACTION_RESULT = "org.videolan.vlc.player.result" const val VLC_INTENT_ACTION_RESULT = "org.videolan.vlc.player.result"
@ -100,7 +102,7 @@ class MainActivity : AppCompatActivity() {
navController.navigate(R.id.navigation_downloads, Bundle(), navOptions) navController.navigate(R.id.navigation_downloads, Bundle(), navOptions)
return true return true
} }
if(child is SearchFragment || child is HomeFragment || child is DownloadFragment || child is SettingsFragment) { if (child is SearchFragment || child is HomeFragment || child is DownloadFragment || child is SettingsFragment) {
this.finish() this.finish()
return true return true
} }
@ -283,7 +285,9 @@ class MainActivity : AppCompatActivity() {
} }
} }
}*/ }*/
/*thread {
createISO()
}*/
handleAppIntent(intent) handleAppIntent(intent)
} }
} }

View file

@ -1,8 +1,11 @@
package com.lagradost.cloudstream3.movieproviders package com.lagradost.cloudstream3.movieproviders
import com.fasterxml.jackson.module.kotlin.readValue
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.utils.AppUtils.imdbUrlToId
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.Qualities
import com.lagradost.cloudstream3.utils.SubtitleHelper
import org.jsoup.Jsoup import org.jsoup.Jsoup
// referer = https://trailers.to, USERAGENT ALSO REQUIRED // referer = https://trailers.to, USERAGENT ALSO REQUIRED
@ -57,7 +60,7 @@ class TrailersToProvider : MainAPI() {
returnList.add(HomePageList(title, currentList)) returnList.add(HomePageList(title, currentList))
} }
} }
if(returnList.size <= 0) return null if (returnList.size <= 0) return null
return HomePageResponse(returnList) return HomePageResponse(returnList)
//section.section > div.container > div.owl-carousel //section.section > div.container > div.owl-carousel
@ -118,14 +121,38 @@ class TrailersToProvider : MainAPI() {
return returnValue return returnValue
} }
private fun loadLink(data: String, callback: (ExtractorLink) -> Unit): Boolean { private fun loadLink(
data: String,
callback: (ExtractorLink) -> Unit,
): Boolean {
val response = khttp.get(data) val response = khttp.get(data)
val url = "<source src='(.*?)'".toRegex().find(response.text)?.groupValues?.get(1) val url = "<source src='(.*?)'".toRegex().find(response.text)?.groupValues?.get(1)
if (url != null) { if (url != null) {
callback.invoke(ExtractorLink(this.name, this.name, url, mainUrl, Qualities.Unknown.value, false)) callback.invoke(ExtractorLink(this.name, this.name, url, mainUrl, Qualities.Unknown.value, false))
return true
} }
return false return url != null
}
private fun loadSubs(url: String, subtitleCallback: (SubtitleFile) -> Unit) {
if (url.isEmpty()) return
val response = khttp.get(fixUrl(url))
val document = Jsoup.parse(response.text)
val items = document.select("div.list-group > a.list-group-item")
for (item in items) {
val hash = item.attr("hash") ?: continue
val languageCode = item.attr("languagecode") ?: continue
if (hash.isEmpty()) continue
if (languageCode.isEmpty()) continue
subtitleCallback.invoke(
SubtitleFile(
SubtitleHelper.fromTwoLettersToLanguage(languageCode) ?: languageCode,
"$mainUrl/subtitles/$hash"
)
)
}
} }
override fun loadLinks( override fun loadLinks(
@ -135,22 +162,35 @@ class TrailersToProvider : MainAPI() {
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
): Boolean { ): Boolean {
if (isCasting) return false if (isCasting) return false
val isMovie = data.contains("/web-sources/") val pairData = mapper.readValue<Pair<String, String>>(data)
val url = pairData.second
val isMovie = url.contains("/web-sources/")
if (isMovie) { if (isMovie) {
return loadLink(data, callback) val isSucc = loadLink(url, callback)
} else if (data.contains("/episode/")) { val subUrl = pairData.first
val response = khttp.get(data) loadSubs(subUrl, subtitleCallback)
return isSucc
} else if (url.contains("/episode/")) {
val response = khttp.get(url)
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response.text)
val qSub = document.select("subtitle-content")
val subUrl = document.select("subtitle-content")?.attr("data-url") ?: ""
val subData = fixUrl(document.selectFirst("content").attr("data-url") ?: return false) val subData = fixUrl(document.selectFirst("content").attr("data-url") ?: return false)
if (subData.contains("/web-sources/")) { val isSucc = if (subData.contains("/web-sources/")) {
return loadLink(subData, callback) loadLink(subData, callback)
} } else false
loadSubs(subUrl, subtitleCallback)
return isSucc
} }
return false return false
} }
override fun load(slug: String): LoadResponse? { override fun load(url: String): LoadResponse? {
val response = khttp.get(slug) val response = khttp.get(url)
val document = Jsoup.parse(response.text) val document = Jsoup.parse(response.text)
val metaInfo = document.select("div.post-info-meta > ul.post-info-meta-list > li") val metaInfo = document.select("div.post-info-meta > ul.post-info-meta-list > li")
val year = metaInfo?.get(0)?.selectFirst("> span.small-text")?.text()?.takeLast(4)?.toIntOrNull() val year = metaInfo?.get(0)?.selectFirst("> span.small-text")?.text()?.takeLast(4)?.toIntOrNull()
@ -175,7 +215,7 @@ class TrailersToProvider : MainAPI() {
} }
val tags = if (generes == null) null else ArrayList(generes) val tags = if (generes == null) null else ArrayList(generes)
val isTvShow = slug.contains("/tvshow/") val isTvShow = url.contains("/tvshow/")
if (isTvShow) { if (isTvShow) {
val episodes = document.select("article.tour-modern") ?: return null val episodes = document.select("article.tour-modern") ?: return null
val parsedEpisodes = episodes.map { item -> val parsedEpisodes = episodes.map { item ->
@ -193,11 +233,21 @@ class TrailersToProvider : MainAPI() {
val ratingText = infoHeaders?.get(1)?.text()?.replace("/ 10", "") val ratingText = infoHeaders?.get(1)?.text()?.replace("/ 10", "")
val epRating = if (ratingText == null) null else parseRating(ratingText) val epRating = if (ratingText == null) null else parseRating(ratingText)
val epDescript = main.selectFirst("> p")?.text() val epDescript = main.selectFirst("> p")?.text()
TvSeriesEpisode(epName, season, episode, href, epPoster, date, epRating, epDescript)
TvSeriesEpisode(
epName,
season,
episode,
mapper.writeValueAsString(Pair("", href)),
epPoster,
date,
epRating,
epDescript
)
} }
return TvSeriesLoadResponse( return TvSeriesLoadResponse(
title, title,
slug, url,
this.name, this.name,
TvType.TvSeries, TvType.TvSeries,
ArrayList(parsedEpisodes), ArrayList(parsedEpisodes),
@ -212,10 +262,21 @@ class TrailersToProvider : MainAPI() {
trailer trailer
) )
} else { } else {
val data = fixUrl(document.selectFirst("content").attr("data-url") ?: return null)
//https://trailers.to/en/subtitle-details/2086212/jungle-cruise-2021?imdbId=tt0870154&season=0&episode=0
//https://trailers.to/en/movie/2086212/jungle-cruise-2021
val subUrl = if (imdbUrl != null) {
val imdbId = imdbUrlToId(imdbUrl)
url.replace("/movie/", "/subtitle-details/") + "?imdbId=$imdbId&season=0&episode=0"
} else ""
val data = mapper.writeValueAsString(
Pair(subUrl, fixUrl(document.selectFirst("content").attr("data-url") ?: return null))
)
return MovieLoadResponse( return MovieLoadResponse(
title, title,
slug, url,
this.name, this.name,
TvType.Movie, TvType.Movie,
data, data,

View file

@ -155,4 +155,12 @@ object AppUtils {
} }
return currentAudioFocusRequest return currentAudioFocusRequest
} }
/** https://www.imdb.com/title/tt2861424/ -> tt2861424 */
fun imdbUrlToId(url: String): String {
return url
.removePrefix("https://www.imdb.com/title/")
.removePrefix("https://imdb.com/title/tt2861424/")
.replace("/", "")
}
} }

View file

@ -0,0 +1,292 @@
package com.lagradost.cloudstream3.utils
import org.jsoup.Jsoup
import java.util.*
object SubtitleHelper {
data class Language639(
val languageName: String,
val nativeName: String,
val ISO_639_1: String,
val ISO_639_2_T: String,
val ISO_639_2_B: String,
val ISO_639_3: String,
val ISO_639_6: String,
)
fun createISO() {
val url = "https://infogalactic.com/info/List_of_ISO_639-1_codes"
val response = khttp.get(url)
val document = Jsoup.parse(response.text)
val headers = document.select("table.wikitable > tbody > tr")
var text = "listOf(\n"
for (head in headers) {
val tds = head.select("td")
if (tds.size < 8) continue
val name = tds[2].selectFirst("> a").text()
val native = tds[3].text()
val ISO_639_1 = tds[4].ownText().replace("+", "").replace(" ", "")
val ISO_639_2_T = tds[5].ownText().replace("+", "").replace(" ", "")
val ISO_639_2_B = tds[6].ownText().replace("+", "").replace(" ", "")
val ISO_639_3 = tds[7].ownText().replace("+", "").replace(" ", "")
val ISO_639_6 = tds[8].ownText().replace("+", "").replace(" ", "")
val txtAdd =
"Language(\"$name\", \"$native\", \"$ISO_639_1\", \"$ISO_639_2_T\", \"$ISO_639_2_B\", \"$ISO_639_3\", \"$ISO_639_6\"),\n"
text += txtAdd
}
text += ")"
println("ISO CREATED:\n$text")
}
/** lang -> ISO_639_1*/
fun fromLanguageToTwoLetters(input: String): String? {
for (lang in languages) {
if (lang.languageName == input || lang.nativeName == input) {
return lang.ISO_639_1
}
}
return null
}
/** ISO_639_1 -> lang*/
fun fromTwoLettersToLanguage(input: String): String? {
if (input.length != 2) return null
val comparison = input.toLowerCase(Locale.ROOT)
for (lang in languages) {
if (lang.ISO_639_1 == comparison) {
return lang.languageName
}
}
return null
}
/**ISO_639_2_B or ISO_639_2_T or ISO_639_3-> lang*/
fun fromThreeLettersToLanguage(input: String): String? {
if (input.length != 3) return null
val comparison = input.toLowerCase(Locale.ROOT)
for (lang in languages) {
if (lang.ISO_639_2_B == comparison) {
return lang.languageName
}
}
for (lang in languages) {
if (lang.ISO_639_2_T == comparison) {
return lang.languageName
}
}
for (lang in languages) {
if (lang.ISO_639_3 == comparison) {
return lang.languageName
}
}
return null
}
/** lang -> ISO_639_2_T*/
fun fromLanguageToThreeLetters(input: String): String? {
for (lang in languages) {
if (lang.languageName == input || lang.nativeName == input) {
return lang.ISO_639_2_T
}
}
return null
}
val languages = listOf(
Language639("Abkhaz", "аҧсуа бызшәа, аҧсшәа", "ab", "abk", "abk", "abk", "abks"),
Language639("Afar", "Afaraf", "aa", "aar", "aar", "aar", "aars"),
Language639("Afrikaans", "Afrikaans", "af", "afr", "afr", "afr", "afrs"),
Language639("Akan", "Akan", "ak", "aka", "aka", "aka", ""),
Language639("Albanian", "Shqip", "sq", "sqi", "", "sqi", ""),
Language639("Amharic", "አማርኛ", "am", "amh", "amh", "amh", ""),
Language639("Arabic", "العربية", "ar", "ara", "ara", "ara", ""),
Language639("Aragonese", "aragonés", "an", "arg", "arg", "arg", ""),
Language639("Armenian", "Հայերեն", "hy", "hye", "", "hye", ""),
Language639("Assamese", "অসমীয়া", "as", "asm", "asm", "asm", ""),
Language639("Avaric", "авар мацӀ, магӀарул мацӀ", "av", "ava", "ava", "ava", ""),
Language639("Avestan", "avesta", "ae", "ave", "ave", "ave", ""),
Language639("Aymara", "aymar aru", "ay", "aym", "aym", "aym", ""),
Language639("Azerbaijani", "azərbaycan dili", "az", "aze", "aze", "aze", ""),
Language639("Bambara", "bamanankan", "bm", "bam", "bam", "bam", ""),
Language639("Bashkir", "башҡорт теле", "ba", "bak", "bak", "bak", ""),
Language639("Basque", "euskara, euskera", "eu", "eus", "", "eus", ""),
Language639("Belarusian", "беларуская мова", "be", "bel", "bel", "bel", ""),
Language639("Bengali", "বাংলা", "bn", "ben", "ben", "ben", ""),
Language639("Bihari", "भोजपुरी", "bh", "bih", "bih", "", ""),
Language639("Bislama", "Bislama", "bi", "bis", "bis", "bis", ""),
Language639("Bosnian", "bosanski jezik", "bs", "bos", "bos", "bos", "boss"),
Language639("Breton", "brezhoneg", "br", "bre", "bre", "bre", ""),
Language639("Bulgarian", "български език", "bg", "bul", "bul", "bul", "buls"),
Language639("Burmese", "ဗမာစာ", "my", "mya", "", "mya", ""),
Language639("Catalan", "català", "ca", "cat", "cat", "cat", ""),
Language639("Chamorro", "Chamoru", "ch", "cha", "cha", "cha", ""),
Language639("Chechen", "нохчийн мотт", "ce", "che", "che", "che", ""),
Language639("Chichewa", "chiCheŵa, chinyanja", "ny", "nya", "nya", "nya", ""),
Language639("Chinese", "中文 (Zhōngwén), 汉语, 漢語", "zh", "zho", "", "zho", ""),
Language639("Chuvash", "чӑваш чӗлхи", "cv", "chv", "chv", "chv", ""),
Language639("Cornish", "Kernewek", "kw", "cor", "cor", "cor", ""),
Language639("Corsican", "corsu, lingua corsa", "co", "cos", "cos", "cos", ""),
Language639("Cree", "ᓀᐦᐃᔭᐍᐏᐣ", "cr", "cre", "cre", "cre", ""),
Language639("Croatian", "hrvatski jezik", "hr", "hrv", "hrv", "hrv", ""),
Language639("Czech", "čeština, český jazyk", "cs", "ces", "", "ces", ""),
Language639("Danish", "dansk", "da", "dan", "dan", "dan", ""),
Language639("Divehi", "ދިވެހި", "dv", "div", "div", "div", ""),
Language639("Dutch", "Nederlands, Vlaams", "nl", "nld", "", "nld", ""),
Language639("Dzongkha", "རྫོང་ཁ", "dz", "dzo", "dzo", "dzo", ""),
Language639("English", "English", "en", "eng", "eng", "eng", "engs"),
Language639("Esperanto", "Esperanto", "eo", "epo", "epo", "epo", ""),
Language639("Estonian", "eesti, eesti keel", "et", "est", "est", "est", ""),
Language639("Ewe", "Eʋegbe", "ee", "ewe", "ewe", "ewe", ""),
Language639("Faroese", "føroyskt", "fo", "fao", "fao", "fao", ""),
Language639("Fijian", "vosa Vakaviti", "fj", "fij", "fij", "fij", ""),
Language639("Finnish", "suomi, suomen kieli", "fi", "fin", "fin", "fin", ""),
Language639("French", "français, langue française", "fr", "fra", "", "fra", "fras"),
Language639("Fula", "Fulfulde, Pulaar, Pular", "ff", "ful", "ful", "ful", ""),
Language639("Galician", "galego", "gl", "glg", "glg", "glg", ""),
Language639("Georgian", "ქართული", "ka", "kat", "", "kat", ""),
Language639("German", "Deutsch", "de", "deu", "", "deu", "deus"),
Language639("Greek", "ελληνικά", "el", "ell", "", "ell", "ells"),
Language639("Guaraní", "Avañe'ẽ", "gn", "grn", "grn", "grn", ""),
Language639("Gujarati", "ગુજરાતી", "gu", "guj", "guj", "guj", ""),
Language639("Haitian", "Kreyòl ayisyen", "ht", "hat", "hat", "hat", ""),
Language639("Hausa", "(Hausa) هَوُسَ", "ha", "hau", "hau", "hau", ""),
Language639("Hebrew", "עברית", "he", "heb", "heb", "heb", ""),
Language639("Herero", "Otjiherero", "hz", "her", "her", "her", ""),
Language639("Hindi", "हिन्दी, हिंदी", "hi", "hin", "hin", "hin", "hins"),
Language639("Hiri Motu", "Hiri Motu", "ho", "hmo", "hmo", "hmo", ""),
Language639("Hungarian", "magyar", "hu", "hun", "hun", "hun", ""),
Language639("Interlingua", "Interlingua", "ia", "ina", "ina", "ina", ""),
Language639("Indonesian", "Bahasa Indonesia", "id", "ind", "ind", "ind", ""),
Language639(
"Interlingue",
"Originally called Occidental; then Interlingue after WWII",
"ie",
"ile",
"ile",
"ile",
""
),
Language639("Irish", "Gaeilge", "ga", "gle", "gle", "gle", ""),
Language639("Igbo", "Asụsụ Igbo", "ig", "ibo", "ibo", "ibo", ""),
Language639("Inupiaq", "Iñupiaq, Iñupiatun", "ik", "ipk", "ipk", "ipk", ""),
Language639("Ido", "Ido", "io", "ido", "ido", "ido", "idos"),
Language639("Icelandic", "Íslenska", "is", "isl", "", "isl", ""),
Language639("Italian", "italiano", "it", "ita", "ita", "ita", "itas"),
Language639("Inuktitut", "ᐃᓄᒃᑎᑐᑦ", "iu", "iku", "iku", "iku", ""),
Language639("Japanese", "日本語 (にほんご)", "ja", "jpn", "jpn", "jpn", ""),
Language639("Javanese", "ꦧꦱꦗꦮ", "jv", "jav", "jav", "jav", ""),
Language639("Kalaallisut", "kalaallisut, kalaallit oqaasii", "kl", "kal", "kal", "kal", ""),
Language639("Kannada", "ಕನ್ನಡ", "kn", "kan", "kan", "kan", ""),
Language639("Kanuri", "Kanuri", "kr", "kau", "kau", "kau", ""),
Language639("Kashmiri", "कश्मीरी, كشميري‎", "ks", "kas", "kas", "kas", ""),
Language639("Kazakh", "қазақ тілі", "kk", "kaz", "kaz", "kaz", ""),
Language639("Khmer", "ខ្មែរ, ខេមរភាសា, ភាសាខ្មែរ", "km", "khm", "khm", "khm", ""),
Language639("Kikuyu", "Gĩkũyũ", "ki", "kik", "kik", "kik", ""),
Language639("Kinyarwanda", "Ikinyarwanda", "rw", "kin", "kin", "kin", ""),
Language639("Kyrgyz", "Кыргызча, Кыргыз тили", "ky", "kir", "kir", "kir", ""),
Language639("Komi", "коми кыв", "kv", "kom", "kom", "kom", ""),
Language639("Kongo", "Kikongo", "kg", "kon", "kon", "kon", ""),
Language639("Korean", "한국어, 조선어", "ko", "kor", "kor", "kor", ""),
Language639("Kurdish", "Kurdî, كوردی‎", "ku", "kur", "kur", "kur", ""),
Language639("Kwanyama", "Kuanyama", "kj", "kua", "kua", "kua", ""),
Language639("Latin", "latine, lingua latina", "la", "lat", "lat", "lat", "lats"),
Language639("Luxembourgish", "Lëtzebuergesch", "lb", "ltz", "ltz", "ltz", ""),
Language639("Ganda", "Luganda", "lg", "lug", "lug", "lug", ""),
Language639("Limburgish", "Limburgs", "li", "lim", "lim", "lim", ""),
Language639("Lingala", "Lingála", "ln", "lin", "lin", "lin", ""),
Language639("Lao", "ພາສາລາວ", "lo", "lao", "lao", "lao", ""),
Language639("Lithuanian", "lietuvių kalba", "lt", "lit", "lit", "lit", ""),
Language639("Luba-Katanga", "Tshiluba", "lu", "lub", "lub", "lub", ""),
Language639("Latvian", "latviešu valoda", "lv", "lav", "lav", "lav", ""),
Language639("Manx", "Gaelg, Gailck", "gv", "glv", "glv", "glv", ""),
Language639("Macedonian", "македонски јазик", "mk", "mkd", "", "mkd", ""),
Language639("Malagasy", "fiteny malagasy", "mg", "mlg", "mlg", "mlg", ""),
Language639("Malay", "bahasa Melayu, بهاس ملايو‎", "ms", "msa", "", "msa", ""),
Language639("Malayalam", "മലയാളം", "ml", "mal", "mal", "mal", ""),
Language639("Maltese", "Malti", "mt", "mlt", "mlt", "mlt", ""),
Language639("Māori", "te reo Māori", "mi", "mri", "", "mri", ""),
Language639("Marathi (Marāṭhī)", "मराठी", "mr", "mar", "mar", "mar", ""),
Language639("Marshallese", "Kajin M̧ajeļ", "mh", "mah", "mah", "mah", ""),
Language639("Mongolian", "Монгол хэл", "mn", "mon", "mon", "mon", ""),
Language639("Nauruan", "Dorerin Naoero", "na", "nau", "nau", "nau", ""),
Language639("Navajo", "Diné bizaad", "nv", "nav", "nav", "nav", ""),
Language639("Northern Ndebele", "isiNdebele", "nd", "nde", "nde", "nde", ""),
Language639("Nepali", "नेपाली", "ne", "nep", "nep", "nep", ""),
Language639("Ndonga", "Owambo", "ng", "ndo", "ndo", "ndo", ""),
Language639("Norwegian Bokmål", "Norsk bokmål", "nb", "nob", "nob", "nob", ""),
Language639("Norwegian Nynorsk", "Norsk nynorsk", "nn", "nno", "nno", "nno", ""),
Language639("Norwegian", "Norsk", "no", "nor", "nor", "nor", ""),
Language639("Nuosu", "ꆈꌠ꒿ Nuosuhxop", "ii", "iii", "iii", "iii", ""),
Language639("Southern Ndebele", "isiNdebele", "nr", "nbl", "nbl", "nbl", ""),
Language639("Occitan", "occitan, lenga d'òc", "oc", "oci", "oci", "oci", ""),
Language639("Ojibwe", "ᐊᓂᔑᓈᐯᒧᐎᓐ", "oj", "oji", "oji", "oji", ""),
Language639("Old Church Slavonic", "ѩзыкъ словѣньскъ", "cu", "chu", "chu", "chu", ""),
Language639("Oromo", "Afaan Oromoo", "om", "orm", "orm", "orm", ""),
Language639("Oriya", "ଓଡ଼ିଆ", "or", "ori", "ori", "ori", ""),
Language639("Ossetian", "ирон æвзаг", "os", "oss", "oss", "oss", ""),
Language639("Panjabi", "ਪੰਜਾਬੀ, پنجابی‎", "pa", "pan", "pan", "pan", ""),
Language639("Pāli", "पाऴि", "pi", "pli", "pli", "pli", ""),
Language639("Persian", "فارسی", "fa", "fas", "", "fas", ""),
Language639("Polish", "język polski, polszczyzna", "pl", "pol", "pol", "pol", "pols"),
Language639("Pashto", "پښتو", "ps", "pus", "pus", "pus", ""),
Language639("Portuguese", "português", "pt", "por", "por", "por", ""),
Language639("Quechua", "Runa Simi, Kichwa", "qu", "que", "que", "que", ""),
Language639("Romansh", "rumantsch grischun", "rm", "roh", "roh", "roh", ""),
Language639("Kirundi", "Ikirundi", "rn", "run", "run", "run", ""),
Language639("Reunion Creole", "Kréol Rénioné", "rc", "rcf", "rcf", "rcf", ""),
Language639("Romanian", "limba română", "ro", "ron", "", "ron", ""),
Language639("Russian", "Русский", "ru", "rus", "rus", "rus", ""),
Language639("Sanskrit (Saṁskṛta)", "संस्कृतम्", "sa", "san", "san", "san", ""),
Language639("Sardinian", "sardu", "sc", "srd", "srd", "srd", ""),
Language639("Sindhi", "सिन्धी, سنڌي، سندھی‎", "sd", "snd", "snd", "snd", ""),
Language639("Northern Sami", "Davvisámegiella", "se", "sme", "sme", "sme", ""),
Language639("Samoan", "gagana fa'a Samoa", "sm", "smo", "smo", "smo", ""),
Language639("Sango", "yângâ tî sängö", "sg", "sag", "sag", "sag", ""),
Language639("Serbian", "српски језик", "sr", "srp", "srp", "srp", ""),
Language639("Scottish Gaelic", "Gàidhlig", "gd", "gla", "gla", "gla", ""),
Language639("Shona", "chiShona", "sn", "sna", "sna", "sna", ""),
Language639("Sinhalese", "සිංහල", "si", "sin", "sin", "sin", ""),
Language639("Slovak", "slovenčina, slovenský jazyk", "sk", "slk", "", "slk", ""),
Language639("Slovene", "slovenski jezik, slovenščina", "sl", "slv", "slv", "slv", ""),
Language639("Somali", "Soomaaliga, af Soomaali", "so", "som", "som", "som", ""),
Language639("Southern Sotho", "Sesotho", "st", "sot", "sot", "sot", ""),
Language639("Spanish", "español", "es", "spa", "spa", "spa", ""),
Language639("Sundanese", "Basa Sunda", "su", "sun", "sun", "sun", ""),
Language639("Swahili", "Kiswahili", "sw", "swa", "swa", "swa", ""),
Language639("Swati", "SiSwati", "ss", "ssw", "ssw", "ssw", ""),
Language639("Swedish", "svenska", "sv", "swe", "swe", "swe", ""),
Language639("Tamil", "தமிழ்", "ta", "tam", "tam", "tam", ""),
Language639("Telugu", "తెలుగు", "te", "tel", "tel", "tel", ""),
Language639("Tajik", "тоҷикӣ, toçikī, تاجیکی‎", "tg", "tgk", "tgk", "tgk", ""),
Language639("Thai", "ไทย", "th", "tha", "tha", "tha", ""),
Language639("Tigrinya", "ትግርኛ", "ti", "tir", "tir", "tir", ""),
Language639("Tibetan Standard", "བོད་ཡིག", "bo", "bod", "", "bod", ""),
Language639("Turkmen", "Türkmen, Түркмен", "tk", "tuk", "tuk", "tuk", ""),
Language639("Tagalog", "Wikang Tagalog", "tl", "tgl", "tgl", "tgl", ""),
Language639("Tswana", "Setswana", "tn", "tsn", "tsn", "tsn", ""),
Language639("Tonga", "faka Tonga", "to", "ton", "ton", "ton", ""),
Language639("Turkish", "Türkçe", "tr", "tur", "tur", "tur", ""),
Language639("Tsonga", "Xitsonga", "ts", "tso", "tso", "tso", ""),
Language639("Tatar", "татар теле, tatar tele", "tt", "tat", "tat", "tat", ""),
Language639("Twi", "Twi", "tw", "twi", "twi", "twi", ""),
Language639("Tahitian", "Reo Tahiti", "ty", "tah", "tah", "tah", ""),
Language639("Uyghur", "ئۇيغۇرچە‎, Uyghurche", "ug", "uig", "uig", "uig", ""),
Language639("Ukrainian", "Українська", "uk", "ukr", "ukr", "ukr", ""),
Language639("Urdu", "اردو", "ur", "urd", "urd", "urd", ""),
Language639("Uzbek", "Oʻzbek, Ўзбек, أۇزبېك‎", "uz", "uzb", "uzb", "uzb", ""),
Language639("Venda", "Tshivenḓa", "ve", "ven", "ven", "ven", ""),
Language639("Vietnamese", "Tiếng Việt", "vi", "vie", "vie", "vie", ""),
Language639("Volapük", "Volapük", "vo", "vol", "vol", "vol", ""),
Language639("Walloon", "walon", "wa", "wln", "wln", "wln", ""),
Language639("Welsh", "Cymraeg", "cy", "cym", "", "cym", ""),
Language639("Wolof", "Wollof", "wo", "wol", "wol", "wol", ""),
Language639("Western Frisian", "Frysk", "fy", "fry", "fry", "fry", ""),
Language639("Xhosa", "isiXhosa", "xh", "xho", "xho", "xho", ""),
Language639("Yiddish", "ייִדיש", "yi", "yid", "yid", "yid", ""),
Language639("Yoruba", "Yorùbá", "yo", "yor", "yor", "yor", ""),
Language639("Zhuang", "Saɯ cueŋƅ, Saw cuengh", "za", "zha", "zha", "zha", ""),
Language639("Zulu", "isiZulu", "zu", "zul", "zul", "zul", ""),
)
}